diff --git a/gnome-extra/gnome-shell-extension-dash-to-dock/Manifest b/gnome-extra/gnome-shell-extension-dash-to-dock/Manifest new file mode 100644 index 0000000..187e342 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-dash-to-dock/Manifest @@ -0,0 +1,2 @@ +DIST gnome-shell-extension-dash-to-dock-72.tar.gz 309825 BLAKE2B be1fcfd11930125bda4befa9d2508c0773812aa5fdfafe4c67797ecbf8c6a95fc3173da21801c1804c0ab71da74e8249d937e072d15fe185d651ab0a634b2ba5 SHA512 a4d2017b9d28c46145cf9cde3e641a7188f0e9febd2a7089973cfacf5b4b5f6f2e402079785b47799e0766d931037bb078ddc37923ae2d4356f764b57f046d28 +EBUILD gnome-shell-extension-dash-to-dock-72.ebuild 1186 BLAKE2B 8b7230e5660737e3c2928098725d571b21b9d1f6221781a5b2150382ef561cbd85da36b81456b3143bc3aba6b3686fa1ab3d301a91da8172ebfd0b6b6978bc33 SHA512 74fbd351566a5dfd436df85795806447c6e16f3deb265b5c0f80c24ebc2264e2e6f8313b2998d09fc7419d54be7b9822df822799ec0895a3201ec899d7f05a8a diff --git a/gnome-extra/gnome-shell-extension-dash-to-dock/gnome-shell-extension-dash-to-dock-72.ebuild b/gnome-extra/gnome-shell-extension-dash-to-dock/gnome-shell-extension-dash-to-dock-72.ebuild new file mode 100644 index 0000000..b5315bb --- /dev/null +++ b/gnome-extra/gnome-shell-extension-dash-to-dock/gnome-shell-extension-dash-to-dock-72.ebuild @@ -0,0 +1,63 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils + +MY_PN="${PN/gnome-shell-extension-/}" + +COMMIT="19cc612c53d33e7c529c116a096bf78c66caae29" + +DESCRIPTION="A dock for the Gnome Shell" +HOMEPAGE="https://github.com/micheleg/dash-to-dock" +SRC_URI="https://github.com/micheleg/dash-to-dock/archive/${COMMIT}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +COMMON_DEPEND=" + dev-libs/glib:2 + dev-lang/sassc +" +RDEPEND="${COMMON_DEPEND} + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-40 +" +DEPEND="${COMMON_DEPEND}" + +BDEPEND="" + +S="${WORKDIR}/${MY_PN}-${COMMIT}" +extension_uuid="dash-to-dock@micxgx.gmail.com" + +src_prepare() { + default + + # Set correct version + export VERSION="${PV}" + + # Don't install README and COPYING in unwanted locations + sed -i -e 's/COPYING//g' -e 's/README.md//g' Makefile || die +} + +src_install() { + default +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} + diff --git a/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/Manifest b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/Manifest new file mode 100644 index 0000000..a004934 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/Manifest @@ -0,0 +1,4 @@ +DIST gnome-shell-extension-maximize-to-empty-workspace-11.tar.gz 15373 BLAKE2B e513b91493c6625404160752b7ea38439f958bf0019d4f2e2c66959e4e2ffad8ec15c9924356d534ea42425f585879e115335af15221ed4f607488efa5fafb80 SHA512 4e66ef00ea3ac8818bcdd0b324521f14c75171a9269e706d9246133c467a12deea5f22642ee86b8cce4fd9eb3ecf1faa06974699bfd414105dec4e3a4c83239d +DIST gnome-shell-extension-maximize-to-empty-workspace-12.tar.gz 15366 BLAKE2B ff91113fdf4208fd2dbe8d244ef3eb4856c23b22490973af87034efefd55a4ce1cfd9a41e3232318243c3890f5f7238a02c198201263a4df587615ecab3740eb SHA512 6350d94755174f9ba8494ce0d181c02802ebc64c041bf02d5dee496e8b3d68b8518b097466026df43ed7617e01935fa5a09134a6297d78e182bb08b9336c58a4 +EBUILD gnome-shell-extension-maximize-to-empty-workspace-11.ebuild 1121 BLAKE2B c7c7dd51422df430bb3c8243ac26e1619007139b04097dae709bcb6dc0306e0fbea931fc0f958cba27849a7235d978524c2908b353163f1de0fbc01881d871b4 SHA512 54ccfe218342a1144173a389f2dcd2f2e0ccaecf75fdd30b9054a78ca5b5f47fdefc5077382f8e9101d3e408bd2db9ecd9769fe405ea33ddb97cf1b1d9d15af5 +EBUILD gnome-shell-extension-maximize-to-empty-workspace-12.ebuild 1121 BLAKE2B de1cce69d2f136752739e78140cde649ea87db92db57ef61438653f116704ea373907ec5f0dff71bc3ba9a27736622e538e0976a4c3d25de208ca9a3e4a04a26 SHA512 744dd737ae0e4cf79d9ef31acaa89dd62e09946dc37f8acd53d7ba1f49ad54bbcc0bcd9d7dae4fd9a45454770134875fd3ed988cf2c74593c6dd1a7e76333d84 diff --git a/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-11.ebuild b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-11.ebuild new file mode 100644 index 0000000..c50078c --- /dev/null +++ b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-11.ebuild @@ -0,0 +1,49 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils + +COMMIT="4edcb61b47d7169ce809513e58d7814990e1f09a" + +DESCRIPTION="New and maximized windows will be moved to empty workspaces.Supports multiple monitors" +HOMEPAGE="https://github.com/kaiseracm/gnome-shell-extension-maximize-to-empty-workspace" +SRC_URI="https://github.com/kaiseracm/gnome-shell-extension-maximize-to-empty-workspace/archive/${COMMIT}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +RDEPEND=" + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-3.38 +" +DEPEND="" +BDEPEND="" + +S="${WORKDIR}/${PN}-${COMMIT}" +extension_uuid="MaximizeToEmptyWorkspace-extension@kaisersite.de" + +src_compile() { :; } + +src_install() { + einstalldocs + insinto /usr/share/gnome-shell/extensions/ + doins -r "${extension_uuid}" +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} diff --git a/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-12.ebuild b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-12.ebuild new file mode 100644 index 0000000..9ee2565 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-maximize-to-empty-workspace/gnome-shell-extension-maximize-to-empty-workspace-12.ebuild @@ -0,0 +1,49 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils + +COMMIT="a9c046d66aeaa142ff7e9382001bfc6a004b1dbb" + +DESCRIPTION="New and maximized windows will be moved to empty workspaces.Supports multiple monitors" +HOMEPAGE="https://github.com/kaiseracm/gnome-shell-extension-maximize-to-empty-workspace" +SRC_URI="https://github.com/kaiseracm/gnome-shell-extension-maximize-to-empty-workspace/archive/${COMMIT}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +RDEPEND=" + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-3.38 +" +DEPEND="" +BDEPEND="" + +S="${WORKDIR}/${PN}-${COMMIT}" +extension_uuid="MaximizeToEmptyWorkspace-extension@kaisersite.de" + +src_compile() { :; } + +src_install() { + einstalldocs + insinto /usr/share/gnome-shell/extensions/ + doins -r "${extension_uuid}" +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} diff --git a/gnome-extra/gnome-shell-extension-no-overview/Manifest b/gnome-extra/gnome-shell-extension-no-overview/Manifest new file mode 100644 index 0000000..f667878 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-no-overview/Manifest @@ -0,0 +1,2 @@ +DIST gnome-shell-extension-no-overview-11.tar.gz 13077 BLAKE2B cfb1c2ab062996798210f13d176f70394e90238ce7487eb420a05d928ddf510965de2f59905d453bfd42fbdfde02ed32e46f33855b82fbac70730238b6c99b85 SHA512 3ec6491ad354ff7f77a28d92f6ba99f14b477bd50b4aa6c9bc148f7c2baf5ff3be69dea4faf11eae4c2a92510509f070cda8329cdbfb73657e77e9172a9447a9 +EBUILD gnome-shell-extension-no-overview-11.ebuild 986 BLAKE2B c28141b28b7f551bb13b001c96dad14413918f34e94900e8cf07b0f621eaab0e753eb9ae9381f30d8c5e0c1d4b01baf7287e4c799245cfbd116f761ee1ae6c70 SHA512 58a0137f9bc8ffe041f361929cb5e554aa4c0a830b0c0fcfa445c1b2d3e043fa942a94e462123884fd116c177a93a686dd2fbf12973b5705c54b8f0ef36b2f01 diff --git a/gnome-extra/gnome-shell-extension-no-overview/gnome-shell-extension-no-overview-11.ebuild b/gnome-extra/gnome-shell-extension-no-overview/gnome-shell-extension-no-overview-11.ebuild new file mode 100644 index 0000000..c562edc --- /dev/null +++ b/gnome-extra/gnome-shell-extension-no-overview/gnome-shell-extension-no-overview-11.ebuild @@ -0,0 +1,49 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils + +DESCRIPTION="No overview at start-up. For GNOME Shell 40+" +HOMEPAGE="https://github.com/fthx/no-overview" +SRC_URI="https://github.com/fthx/no-overview/archive/v${PV}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-3" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +COMMON_DEPEND=" + dev-libs/glib:2 +" +RDEPEND="${COMMON_DEPEND} + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-40.0 +" +DEPEND="${COMMON_DEPEND}" +BDEPEND="" + +S="${WORKDIR}/no-overview-${PV}" +extension_uuid="no-overview@fthx" + +src_install() { + einstalldocs + rm -f README.md LICENSE || die + insinto /usr/share/gnome-shell/extensions/"${extension_uuid}" + doins -r * +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} diff --git a/gnome-extra/gnome-shell-extension-remove-app-menu/Manifest b/gnome-extra/gnome-shell-extension-remove-app-menu/Manifest new file mode 100644 index 0000000..b52ec12 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-remove-app-menu/Manifest @@ -0,0 +1,3 @@ +AUX remove-app-menu-makefile-9.0.patch 928 BLAKE2B 466c172b90a799d19c01d023173e858b103b74c3edb0ecc661221c51a2b6422fb18e85d1238de83424ef636533a9c42e6671c60fbf0900e94652aac7b297946d SHA512 4d774264e3f35af75518c88a7a7a85df47d34e2a83f24b51f7372a0146c4c47ad16a6709984ca78d3f549a4d6620127131a335a7d67d69d2eaf0a8144a8a47e4 +DIST gnome-shell-extension-remove-app-menu-9.0.tar.gz 18273 BLAKE2B ad710144138a0fc38954db52214564ca2488ad627f91134871c73321961526300f524b0746ff995205ea120aa71031e95bcb8da27adcf0a53db5773792bec071 SHA512 f5dd97f2d0fe2422d595ed143619dd22d57e196fcf478122060c33d0d290258a5e1379cd32536a4672e6eb67b09e988b009da0efcee66fade25eda755df10069 +EBUILD gnome-shell-extension-remove-app-menu-9.0.ebuild 1080 BLAKE2B fda2fa31c0e30f7b8ac6c71f334f89f9fee933344fd4b65fae4b7f279ec30aa54d9bc1bd0106024041d3331c48b7d59e9d2f740ad397bbaa285c29b04d69ecef SHA512 fd443e3943a9e9a2fd541914ef19be709d72c93d49b3cc5a481e93f300c9921ea6fb07bd8b92c86c52dad2b554c912c83b5dc31051a4e06a3505de1adb486fbd diff --git a/gnome-extra/gnome-shell-extension-remove-app-menu/files/remove-app-menu-makefile-9.0.patch b/gnome-extra/gnome-shell-extension-remove-app-menu/files/remove-app-menu-makefile-9.0.patch new file mode 100644 index 0000000..e3e2c17 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-remove-app-menu/files/remove-app-menu-makefile-9.0.patch @@ -0,0 +1,38 @@ + +diff --git a/Makefile b/Makefile + +--- a/Makefile 2022-03-12 14:06:41.000000000 +0300 ++++ b/Makefile 2022-07-03 17:18:34.966377020 +0300 +@@ -4,6 +4,13 @@ + + PNG_FILES=$(wildcard ./docs/*.png) + ++ifeq ($(strip $(DESTDIR)), ) ++ INSTALL_DIR_TYPE = local ++else ++ INSTALL_DIR_TYPE = system ++ SHARE_PREFIX = $(DESTDIR)/usr/share ++endif ++ + .PHONY: build check prune compress install uninstall clean $(PNG_FILES) + + build: +@@ -20,8 +27,17 @@ + $(MAKE) $(PNG_FILES) + $(PNG_FILES): + optipng "$(COMPRESSLEVEL)" -strip all "$@" +-install: ++install: install-local ++ ++install-local: + gnome-extensions install "$(UUID).shell-extension.zip" --force ++ ++ifeq ($(INSTALL_DIR_TYPE), system) ++ mkdir -p $(SHARE_PREFIX)/gnome-shell ++ mkdir -p $(SHARE_PREFIX)/gnome-shell/extensions ++ mv $(HOME)/.local/share/gnome-shell/extensions/$(UUID) $(SHARE_PREFIX)/gnome-shell/extensions/ ++endif ++ + uninstall: + gnome-extensions uninstall "$(UUID)" + clean: diff --git a/gnome-extra/gnome-shell-extension-remove-app-menu/gnome-shell-extension-remove-app-menu-9.0.ebuild b/gnome-extra/gnome-shell-extension-remove-app-menu/gnome-shell-extension-remove-app-menu-9.0.ebuild new file mode 100644 index 0000000..ec7574d --- /dev/null +++ b/gnome-extra/gnome-shell-extension-remove-app-menu/gnome-shell-extension-remove-app-menu-9.0.ebuild @@ -0,0 +1,54 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils + +MY_PN="${PN/gnome-shell-extension-/}-extension" +MY_P="${MY_PN}-${PV}" + +DESCRIPTION="Remove the application menu from the top bar" +HOMEPAGE="https://github.com/stuarthayhurst/remove-app-menu-extension" +SRC_URI="https://github.com/stuarthayhurst/${MY_PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +COMMON_DEPEND="dev-libs/glib:2" +RDEPEND="${COMMON_DEPEND} + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-3.36 +" +DEPEND="${COMMON_DEPEND}" +BDEPEND="" + +S="${WORKDIR}/${MY_P}" +extension_uuid="RemoveAppMenu@Dragon8oy.com" + +src_prepare() { + eapply "${FILESDIR}"/remove-app-menu-makefile-9.0.patch + eapply_user +} + +src_install() { + default +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} + + diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/Manifest b/gnome-extra/gnome-shell-extension-tweaks-system-menu/Manifest new file mode 100644 index 0000000..4e1ca67 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/Manifest @@ -0,0 +1,6 @@ +AUX tweaks-system-menu-build-meson.patch 2564 BLAKE2B 4831129b6c9b4b316c817a9b1d1a1cfc8cd7813ae5e2ff7db5a7e509f60331cf9fe96b04652b5a430c23cae7bc6e0b623efa3a150617a75e44bd2aab35591640 SHA512 9d793bb2f678f96b3ec7fbe8fe0210a4c3abf10af6e6c61dccbbfecc311d4a819c69fd95f2bbfffe66c99b2f1f3570da97dad16df96c077eb469a56ee225c02f +AUX tweaks-system-menu-gse-build-meson.patch 2243 BLAKE2B 085b5b0651307aaff01c750d0e56fccfa38b7aa54cd32cf1c8a084a21967f96f8fc70ff4eb6584c376b88c962e87af45a782b9a6a58a41440c249d2dafe7e95c SHA512 e41227849b6d026ad47ac5d6184b25242e52d77ae944ee50d8aed5529987a976aec2976de93ec23e58b78ecede90dedf43512b4cfb32570e880bb7e77dd51d45 +AUX tweaks-system-menu-gse-meson_options.patch 297 BLAKE2B 94a9df1ba090c9272a308b5d884d661a6adfbc081a7327bf6e5eb62db3db4e669ba22afe4df91935207c697d119c51193cfb129863ddf9fdc5f36d805dc914f9 SHA512 c3fc14844402374d333c3011e125160df63ea86ba80245688ef0ecc11abb632d788dd269c7bc9c85571493c1c73d47f988dab2df793c20a046422b10ce015670 +AUX tweaks-system-menu-meson_options.patch 257 BLAKE2B 66eb68534d431eba2f3886871a894fe124d76977562a04cc401decd613df26eba9833f27f0998bc25e57db3d57c9eca75d04581728eae3d7e2950a79c72e88cc SHA512 c4d1c3b31f13f1e3f887575b9bbc493a981d0444febfd315a01b6fd4e4706e3046d3bf3ca0a5a057cd7d63be20d0582a2d199d795c756dacba5cfd7a1c1d13a9 +DIST gnome-shell-extension-tweaks-system-menu-18.tar.gz 155621 BLAKE2B 0af570b8112bf5907626b631fd92e897edacbcd7f0ccb0e7903ef315fb0d98a97ae21a519fd4e9353dfb84515916759fc47b17c50f17a9ffb2ca5205204bea87 SHA512 346b5309af290e511464e9b84ffd5f7471298009613d0806bcd2f2137795a6079a14b97e73d83ad9c337c0342778b5a7b2bf339943a83835ff530aad5a49252d +EBUILD gnome-shell-extension-tweaks-system-menu-18.ebuild 1532 BLAKE2B e7a9289aee446b8aea5a264459f3a2959e250c158001bd4d003e05f1e4c8228a6f2277b18e1ace23a3c4d7666b938ca43c95d7e356ef78b204be0c35125d0f16 SHA512 1bbec8bed4c68cedbc29d4f5886cf7b24fb8ff3e03f2fe8da5061f4a7b3917100f22c39d483237e7ee25d77a82b5da45a3bc0d9aa3ffaca023e6c93499dea650 diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-build-meson.patch b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-build-meson.patch new file mode 100644 index 0000000..8770bfe --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-build-meson.patch @@ -0,0 +1,69 @@ + +diff --git a/meson.build b/meson.build + +--- a/meson.build 2022-03-13 02:03:28.000000000 +0300 ++++ b/meson.build 2022-07-03 00:10:51.622845000 +0300 +@@ -43,6 +43,15 @@ + gnome = import('gnome') + i18n = import('i18n') + ++if get_option('local_install').auto() ++ gse_local_install = false ++ if get_option('prefix') == '/usr/local' ++ gse_local_install = run_command(find_program('id'), '-u').stdout().strip() != '0' ++ endif ++else ++ gse_local_install = get_option('local_install').enabled() ++endif ++ + gse_lib_convenience = files('meson-gse/lib/convenience.js') + gse_lib_logger = files('meson-gse/lib/logger.js') + +@@ -69,6 +78,7 @@ + gse_schemas += files(gse_schema_main) + endif + ++gse_js91 = find_program('js91', required: false) + gse_js78 = find_program('js78', required: false) + gse_js68 = find_program('js68', required: false) + gse_js60 = find_program('js60', required: false) +@@ -84,17 +94,28 @@ + # End of extension-specific settings + + # Boilerplate +-gse_run_command_obj = run_command('sh', '-c', 'echo $HOME') +-if gse_run_command_obj.returncode() != 0 +- error('HOME not found, exit=@0@'.format(gse_run_command_obj.returncode())) +-endif +-home = gse_run_command_obj.stdout().strip() +- +-gse_uuid = meson.project_name() + '@extensions.gnome-shell.fifi.org' +-gse_target_dir = home + '/.local/share/gnome-shell/extensions/' + gse_uuid +-gse_target_dir_schemas = join_paths(gse_target_dir, 'schemas') +-gse_target_locale_dir = join_paths(gse_target_dir, 'locale') +-gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++if gse_local_install ++ gse_run_command_obj = run_command('sh', '-c', 'echo $HOME') ++ if gse_run_command_obj.returncode() != 0 ++ error('HOME not found, exit=@0@'.format(gse_run_command_obj.returncode())) ++ endif ++ prefix = gse_run_command_obj.stdout().strip() / '.local' ++else ++ prefix = get_option('prefix') ++endif ++ ++gse_uuid = meson.project_name() + '@extensions.gnome-shell.fifi.org' ++gse_target_dir = prefix + '/share/gnome-shell/extensions/' + gse_uuid ++ ++if gse_local_install ++ gse_target_dir_schemas = join_paths(gse_target_dir, 'schemas') ++ gse_target_locale_dir = join_paths(gse_target_dir, 'locale') ++ gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++else ++ gse_target_dir_schemas = prefix / get_option('datadir') / 'glib-2.0' / 'schemas' ++ gse_target_locale_dir = prefix / get_option('localedir') ++ gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++endif + + meson_extra_scripts = 'meson-gse/meson-scripts' + diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-build-meson.patch b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-build-meson.patch new file mode 100644 index 0000000..5ca60f4 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-build-meson.patch @@ -0,0 +1,58 @@ + +diff --git a/meson-gse/meson.build.m4 b/meson-gse/meson.build.m4 + +--- a/meson-gse/meson.build.m4 2022-03-13 02:03:28.000000000 +0300 ++++ b/meson-gse/meson.build.m4 2022-07-03 10:19:07.080321000 +0300 +@@ -63,6 +63,15 @@ + gnome = import('gnome') + i18n = import('i18n') + ++if get_option('local_install').auto() ++ gse_local_install = false ++ if get_option('prefix') == '/usr/local' ++ gse_local_install = run_command(find_program('id'), '-u').stdout().strip() != '0' ++ endif ++else ++ gse_local_install = get_option('local_install').enabled() ++endif ++ + gse_lib_convenience = files('meson-gse/lib/convenience.js') + gse_lib_logger = files('meson-gse/lib/logger.js') + +@@ -97,17 +106,28 @@ + # End of extension-specific settings + + # Boilerplate +-gse_run_command_obj = run_command('sh', '-c', 'echo $HOME') +-if gse_run_command_obj.returncode() != 0 +- error('HOME not found, exit=@0@'.format(gse_run_command_obj.returncode())) ++if gse_local_install ++ gse_run_command_obj = run_command('sh', '-c', 'echo $HOME') ++ if gse_run_command_obj.returncode() != 0 ++ error('HOME not found, exit=@0@'.format(gse_run_command_obj.returncode())) ++ endif ++ prefix = gse_run_command_obj.stdout().strip() / '.local' ++else ++ prefix = get_option('prefix') + endif +-home = gse_run_command_obj.stdout().strip() + + gse_uuid = meson.project_name() + '@$2' +-gse_target_dir = home + '/.local/share/gnome-shell/extensions/' + gse_uuid +-gse_target_dir_schemas = join_paths(gse_target_dir, 'schemas') +-gse_target_locale_dir = join_paths(gse_target_dir, 'locale') +-gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++gse_target_dir = prefix + '/share/gnome-shell/extensions/' + gse_uuid ++ ++if gse_local_install ++ gse_target_dir_schemas = join_paths(gse_target_dir, 'schemas') ++ gse_target_locale_dir = join_paths(gse_target_dir, 'locale') ++ gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++else ++ gse_target_dir_schemas = prefix / get_option('datadir') / 'glib-2.0' / 'schemas' ++ gse_target_locale_dir = prefix / get_option('localedir') ++ gse_target_dir_dbus_intf = join_paths(gse_target_dir, 'dbus-interfaces') ++endif + + meson_extra_scripts = 'meson-gse/meson-scripts' + diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-meson_options.patch b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-meson_options.patch new file mode 100644 index 0000000..a99bb22 --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-gse-meson_options.patch @@ -0,0 +1,9 @@ + +diff --git a/meson-gse/meson_options.txt b/meson-gse/meson_options.txt + +--- a/meson-gse/meson_options.txt 2022-07-03 09:46:05.402049000 +0300 ++++ b/meson-gse/meson_options.txt 2022-07-02 21:36:21.250190000 +0300 +@@ -0,0 +1,3 @@ ++option('local_install', ++ type: 'feature', ++ value : 'auto') diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-meson_options.patch b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-meson_options.patch new file mode 100644 index 0000000..3ca3bfc --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/files/tweaks-system-menu-meson_options.patch @@ -0,0 +1,9 @@ + +diff --git a/meson_options.txt b/meson_options.txt + +--- a/meson_options.txt 2022-07-03 09:46:05.402049893 +0300 ++++ b/meson_options.txt 2022-07-02 21:36:21.250190000 +0300 +@@ -0,0 +1,3 @@ ++option('local_install', ++ type: 'feature', ++ value : 'auto') diff --git a/gnome-extra/gnome-shell-extension-tweaks-system-menu/gnome-shell-extension-tweaks-system-menu-18.ebuild b/gnome-extra/gnome-shell-extension-tweaks-system-menu/gnome-shell-extension-tweaks-system-menu-18.ebuild new file mode 100644 index 0000000..6c65f2c --- /dev/null +++ b/gnome-extra/gnome-shell-extension-tweaks-system-menu/gnome-shell-extension-tweaks-system-menu-18.ebuild @@ -0,0 +1,71 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 +inherit gnome2-utils meson + +MY_PN="${PN/gnome-shell-extension-/}" + +DESCRIPTION="Put Gnome Tweaks and Extensions (on Shell 40 and later) in the System menu" +HOMEPAGE="https://github.com/F-i-f/tweaks-system-menu" +SRC_URI="https://github.com/F-i-f/${MY_PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +KEYWORDS="amd64 x86" +IUSE="" + +COMMON_DEPEND="dev-libs/glib:2" +RDEPEND="${COMMON_DEPEND} + app-eselect/eselect-gnome-shell-extensions + >=gnome-base/gnome-shell-40.0 +" +DEPEND="${COMMON_DEPEND}" +BDEPEND=" + virtual/pkgconfig + >=dev-util/meson-0.50.0 +" + +S="${WORKDIR}/${MY_PN}-${PV}" +extension_uuid="tweaks-system-menu@extensions.gnome-shell.fifi.org" + + +src_prepare() { + eapply "${FILESDIR}"/${MY_PN}-build-meson.patch + eapply "${FILESDIR}"/${MY_PN}-gse-build-meson.patch + eapply "${FILESDIR}"/${MY_PN}-meson_options.patch + eapply "${FILESDIR}"/${MY_PN}-gse-meson_options.patch + eapply_user +} + +src_configure() { + meson_src_configure +} + +src_compile() { + meson_src_compile +} + +src_install() { + meson_src_install + + # Install schemas system-wide + dodir /usr/share/glib-2.0/schemas + rm "${ED}/usr/share/glib-2.0/schemas/gschemas.compiled" || die +} + +pkg_preinst() { + gnome2_schemas_savelist +} + +pkg_postinst() { + gnome2_schemas_update + ebegin "Updating list of installed extensions" + eselect gnome-shell-extensions update + eend $? +} + +pkg_postrm() { + gnome2_schemas_update +} + diff --git a/metadata/layout.conf b/metadata/layout.conf new file mode 100644 index 0000000..3fb1bc6 --- /dev/null +++ b/metadata/layout.conf @@ -0,0 +1,15 @@ +# Slave repository rather than stand-alone +masters = gentoo + +# Use thin manifests +thin-manifests = true + +# Dont sign thin manifests. There is no current policy for git commit signing +sign-manifests = false + +# Make egencache generate newer (more reliable) +# md5-dict cache format +cache-formats = md5-dict + +# Support package.* directories as well as files +profile-formats = portage-2 diff --git a/net-misc/yandex-disk/Manifest b/net-misc/yandex-disk/Manifest new file mode 100644 index 0000000..1794e9f --- /dev/null +++ b/net-misc/yandex-disk/Manifest @@ -0,0 +1,2 @@ +DIST yandex-disk-0.1.6.1080-1.fedora.i386.rpm 4613067 BLAKE2B 1d893b0420d6146aea7d10d4603c28fccd6e6c93eb3c6c414d5c91b3ebd77dd770fc20445b5c0e5892994a32d9fdfa18d3aa5cc011be3894381e63b833b76630 SHA512 68f8952556b822d1de0b99827f4667257caab8ff3c744c280da682d7bf9647877dcbad5547946f92d230bd8dd27b50f5695e5af6cdd6c8c4ed20ca22cbe5e914 +DIST yandex-disk-0.1.6.1080-1.fedora.x86_64.rpm 4799367 BLAKE2B cc0fabe1479c0c66b06dd7fab943de32e1ad9477b3c03bc39c0859ba5b802bad8909d721b5fc2445943e86213bcc9ce68bf5f37eb6c151d5c211243176ae126c SHA512 d0845a825b1d4db773947c1101fa6aee38df43167486e4fae1d2db1e7fc7a49326882848eb742b069b3b2f6c1e9d617f6203dd8a3f67dd136dfa1f7bc1c8bfea diff --git a/net-misc/yandex-disk/yandex-disk-0.1.6.1080_p1.ebuild b/net-misc/yandex-disk/yandex-disk-0.1.6.1080_p1.ebuild new file mode 100644 index 0000000..b8c324f --- /dev/null +++ b/net-misc/yandex-disk/yandex-disk-0.1.6.1080_p1.ebuild @@ -0,0 +1,50 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit bash-completion-r1 rpm + +MY_P="${PN}-${PV/_p/-}" + +DESCRIPTION="CLI to access Yandex Disk file storage service" +HOMEPAGE="https://disk.yandex.ru" +SRC_URI=" + amd64? ( https://repo.yandex.ru/yandex-disk/rpm/stable/x86_64/${MY_P}.fedora.x86_64.rpm ) + x86? ( https://repo.yandex.ru/yandex-disk/rpm/stable/i386/${MY_P}.fedora.i386.rpm ) +" + +LICENSE="YDSLA" +SLOT="0" +KEYWORDS="-* ~amd64 ~x86" + +DEPEND="app-arch/gzip" +RDEPEND="sys-libs/zlib" + +S="${WORKDIR}" + +QA_PREBUILT="opt/bin/yandex-disk" + +src_prepare() { + # bug #526312 + sed -i \ + -e '/have /d' \ + -e 's/+o nospace/-o nospace/' \ + -e '/^complete/s/-X //' \ + etc/bash_completion.d/yandex-disk-completion.bash || die + + # Uncompress man pages to prevent QA warnings, bug #731684 + find usr/share/man -type f -name *.gz | xargs gunzip + + eapply_user +} + +src_install() { + exeinto /opt/bin + doexe usr/bin/yandex-disk + newbashcomp etc/bash_completion.d/yandex-disk-completion.bash "${PN}" + insinto /usr/share/man + doins -r usr/share/man/* + insinto /usr/share + doins -r usr/share/locale +} diff --git a/net-wireless/rtl88x2bu/Manifest b/net-wireless/rtl88x2bu/Manifest new file mode 100644 index 0000000..6ecd047 --- /dev/null +++ b/net-wireless/rtl88x2bu/Manifest @@ -0,0 +1,4 @@ +DIST rtl88x2bu-20211010.tar.gz 4029432 BLAKE2B d94c623f746c8d3ecc235d06b16c1b266017f4aa0f558d8c64095b943c3595f040979e444f95623589ac468dd86ba3365fcffa90e5f362b58a50b2637f8fd0ec SHA512 5b75b7d9529efab3f6c53278f5b3399f228bb6de63f8fdf79a80f8b8482ce50a15a82d8ed4af58a50218657346eead4d3ad367e06d2542d0b2e5c2767f7e6879 +DIST rtl88x2bu-20220523.tar.gz 4029989 BLAKE2B 11a37518810412d16156aa76d58031e2da8547cb76ed7d1bcf1df97fe2ed1f02aeec109a273c75e8a25ef5647b0cec1f4332fd6c8a6bc6fa4264215d7b6845ea SHA512 a084fc8fd20e48e777e5ff8813d28dc0ed7935e7bcc6cd2cb404f4f700cdfb6a1aa1fe171685bd1661386885aa1f0f4571d9b57d93ce7743499b750e1e195a3a +EBUILD rtl88x2bu-20211010.ebuild 934 BLAKE2B 002be5bc5f70417e4c41011c0f9921dce368b85b0dd344ee4bf0857151a50f70ff4232bab309f071fa062d8331279febeefc8895c8107bee18cb0911089f838f SHA512 37f48027ae8c3af0617eb68e1911dc1e69f2025d0dec389499d161e20aef0ddbd3744e9aeab726208bada9885861791c8916e3495f1efb2ec7e7a62b4d67d8ed +EBUILD rtl88x2bu-20220523.ebuild 966 BLAKE2B 6acdb78643321286cb738ff87447710e28999c425d1084eab2db26d1908ca2604e690a0f65746378b363cf801fd83b7d55dac20c5dbfb21012bf0a1f1c7a9f28 SHA512 eb480d1641a8187b1f48fb3b8132e10cb230b061b9e27b971c072ffa51ad21532157f670c0f54c3ac974847c7e000825bec6017ff9a4755096b3ca3e65b05ead diff --git a/net-wireless/rtl88x2bu/rtl88x2bu-20211010.ebuild b/net-wireless/rtl88x2bu/rtl88x2bu-20211010.ebuild new file mode 100644 index 0000000..d153c7c --- /dev/null +++ b/net-wireless/rtl88x2bu/rtl88x2bu-20211010.ebuild @@ -0,0 +1,47 @@ +# Copyright 2021 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +inherit linux-mod + +COMMIT="e8ad266af883b60e88012957e89bf361924ea5ec" + +DESCRIPTION="rtl88x2bu driver updated for current kernels" +HOMEPAGE="https://github.com/cilynx/rtl88x2bu" +SRC_URI="https://github.com/cilynx/rtl88x2bu/archive/${COMMIT}.tar.gz -> rtl88x2bu-${PV}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64" + +RDEPEND="virtual/linux-sources" +DEPEND="${RDEPEND}" + +S="${WORKDIR}/rtl88x2bu-${COMMIT}" + +MODULE_NAMES="88x2bu(net/wireless)" +BUILD_TARGETS="all" +BUILD_TARGET_ARCH="${ARCH}" + +pkg_setup() { + if ! use kernel_linux ; then + die "Unable to install" + fi + + linux-mod_pkg_setup + BUILD_PARAMS="KERN_DIR=${KV_DIR} KSRC=${KV_DIR} KERN_VER=${KV_FULL} O=${KV_OUT_DIR} V=1 KBUILD_VERBOSE=1" +} + +src_compile(){ + linux-mod_src_compile +} + +src_install() { + linux-mod_src_install +} + +pkg_postinst() { + linux-mod_pkg_postinst +} + diff --git a/net-wireless/rtl88x2bu/rtl88x2bu-20220523.ebuild b/net-wireless/rtl88x2bu/rtl88x2bu-20220523.ebuild new file mode 100644 index 0000000..b50d125 --- /dev/null +++ b/net-wireless/rtl88x2bu/rtl88x2bu-20220523.ebuild @@ -0,0 +1,48 @@ +# Copyright 2022 Calculate Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +inherit linux-mod + +COMMIT="9957138ac30529a06bfcbc36eb51006a948b0967" + +DESCRIPTION="rtl88x2bu driver updated for current kernels" +HOMEPAGE="https://github.com/cilynx/rtl88x2bu" +SRC_URI="https://github.com/cilynx/rtl88x2bu/archive/${COMMIT}.tar.gz -> rtl88x2bu-${PV}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64" +IUSE="dist-kernel" + +RDEPEND="virtual/linux-sources" +DEPEND="${RDEPEND}" + +S="${WORKDIR}/rtl88x2bu-${COMMIT}" + +MODULE_NAMES="88x2bu(net/wireless)" +BUILD_TARGETS="clean modules" +BUILD_TARGET_ARCH="${ARCH}" + +pkg_setup() { + if ! use kernel_linux ; then + die "Unable to install" + fi + + linux-mod_pkg_setup + BUILD_PARAMS="KERN_DIR=${KV_DIR} KSRC=${KV_DIR} KERN_VER=${KV_FULL} O=${KV_OUT_DIR} V=1 KBUILD_VERBOSE=1" +} + +src_compile(){ + linux-mod_src_compile +} + +src_install() { + linux-mod_src_install +} + +pkg_postinst() { + linux-mod_pkg_postinst +} + diff --git a/profiles/CLDG/amd64/20/calculate.env b/profiles/CLDG/amd64/20/calculate.env new file mode 100644 index 0000000..7e8a26d --- /dev/null +++ b/profiles/CLDG/amd64/20/calculate.env @@ -0,0 +1,3 @@ +[main] +cl_template_location = calculate,distros,gnome-distro,local,remote +cl_template_path = /var/db/repos/calculate/profiles/templates,/var/db/repos/distros/profiles/templates,/var/db/repos/gnome-distro/profiles/templates,/var/calculate/templates,/var/calculate/remote/templates diff --git a/profiles/CLDG/amd64/20/parent b/profiles/CLDG/amd64/20/parent new file mode 100644 index 0000000..42d0e62 --- /dev/null +++ b/profiles/CLDG/amd64/20/parent @@ -0,0 +1,2 @@ +calculate:default/amd64/20/desktop +../.. diff --git a/profiles/CLDG/amd64/parent b/profiles/CLDG/amd64/parent new file mode 100644 index 0000000..410f9d0 --- /dev/null +++ b/profiles/CLDG/amd64/parent @@ -0,0 +1,2 @@ +../../../../calculate/profiles/default/amd64/18/desktop +.. diff --git a/profiles/CLDG/calculate.env b/profiles/CLDG/calculate.env new file mode 100644 index 0000000..8a9bafc --- /dev/null +++ b/profiles/CLDG/calculate.env @@ -0,0 +1,6 @@ +[main] +os_linux_name = 'Calculate Linux Desktop' +os_linux_subname = 'GNOME' +os_linux_shortname = CLDG +[update] +cl_update_with_bdeps_set = on diff --git a/profiles/CLDG/make.defaults b/profiles/CLDG/make.defaults new file mode 100644 index 0000000..690b993 --- /dev/null +++ b/profiles/CLDG/make.defaults @@ -0,0 +1,3 @@ +# Calculate Linux Gnome +USE="-systemd -consolekit" +THEMES="CLDG" diff --git a/profiles/CLDG/package.accept_keywords b/profiles/CLDG/package.accept_keywords new file mode 100644 index 0000000..c35e27a --- /dev/null +++ b/profiles/CLDG/package.accept_keywords @@ -0,0 +1,4 @@ +# required by net-wireless/rtl88x2bu (argument) +=net-wireless/rtl88x2bu-20220523 ~amd64 +# required by sys-power/power-profiles-daemon (argument) +=sys-power/power-profiles-daemon-0.11.1 ~amd64 diff --git a/profiles/CLDG/package.mask b/profiles/CLDG/package.mask new file mode 100644 index 0000000..c91cfcc --- /dev/null +++ b/profiles/CLDG/package.mask @@ -0,0 +1,5 @@ +# gnome-base/gnome-control-center +>=gnome-base/gnome-control-center-43.1 + +# x11-terms/gnome-terminal +>=x11-terms/gnome-terminal-3.46.3 diff --git a/profiles/CLDG/package.use b/profiles/CLDG/package.use new file mode 100644 index 0000000..8010239 --- /dev/null +++ b/profiles/CLDG/package.use @@ -0,0 +1,124 @@ +# Calculate +sys-apps/calculate-utils client qt5 + +# GNOME + +# Recommended by Gentoo Foundation + +# Copyright 1999-2021 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# Mart Raudsepp (2022-01-05) +# gnome-boxes requires spice-gtk[vala] +# net-misc/spice-gtk vala + +# Mart Raudsepp (2021-08-13) +# evolution-data-server requires libical[vala] and libgdata[vala] by default +# dev-libs/libical vala +# dev-libs/libgdata vala + +# Marek Szuba (2021-03-18) +# FUSE cannot be built with multiple audio drivers, and desktop/gnome +# profiles set both USE=pulseaudio (directly) and USE=alsa (inherited +# from desktop). Default to the latter for now because PulseAudio support +# in FUSE is currently considered experimental. +# app-emulation/fuse -pulseaudio + +# REQUIRED_USE constraint when pulseaudio is enabled +# dev-libs/efl sound + +# Needed by gnome-photos +# media-libs/gegl raw + +# Needed by a global USE=wayland right now; some REQUIRED_USE may be outdated and need review +# >=media-libs/cogl-1.18.2-r1 gles2 +# >=media-libs/clutter-1.20 egl +# media-libs/cogl kms +# media-libs/libsdl2 gles2 + +# Needed by mutter defaults and USE=wayland, bug #547300 +>=media-libs/mesa-10.3 gbm gles2 + +# For eautoreconf in =app-crypt/seahorse-3.10.2-r1 +# app-crypt/gcr vala + +# Required by folks, needed by empathy +# >=gnome-extra/evolution-data-server-3.8 vala + +# Required for cheese in gnome3 +# >=media-libs/gst-plugins-base-1.0 theora + +# Required for gnome-base/gnome-2.32 to be merged directly, for +# gnome-extra/hamster-applet-2.32 and x11-misc/alacarte-0.13 +# dev-lang/python sqlite + +# Required by app-accessibility/orca-3 +# app-accessibility/speech-dispatcher python + +# Pulled in by grilo-plugins which is needed for gnome-music +# media-libs/grilo playlist + +# Pulled in by tracker and grilo-plugins, has REQUIRED_USE="?? ( gtk qt5 )" +# media-libs/libmediaart gtk -qt5 + +# For gnome-boxes +# net-misc/spice-gtk gtk3 + +# Recommended by Adrian. URI https://github.com/aaaaadrien/adrien-overlay + +# Extra by Adrien +gnome-extra/evolution-data-server oauth + +# Elogind +# net-misc/networkmanager -elogind +# media-sound/pulseaudio elogind + +# GNOME without games by default +gnome-base/gnome-extra-apps -games + +# GNOME Software only for extensions - Пакет не установлен +# gnome-extra/gnome-software -firmware + +# Garde binaires +net-libs/webkit-gtk -gnome-keyring +www-client/chromium -gnome-keyring +media-gfx/gimp -gnome +media-video/vlc -gnome-keyring + +# Recommended by Jksf + +# Transmission +net-p2p/transmission -qt5 gtk + +# Recommended USE +gnome-base/nautilus gnome +gnome-base/gvfs gnome-online-accounts +dev-vcs/git gnome-keyring +net-libs/libproxy gnome +net-misc/remmina gnome-keyring +net-libs/glib-networking gnome +net-libs/gnome-online-accounts gnome + +# Пакет может не собираться с USE = gnome +x11-wm/mutter gnome + +x11-misc/xdg-utils gnome +x11-themes/adwaita-qt gnome +x11-terms/gnome-terminal gnome-shell nautilus + +# Происходит циклическая зависимость пакетов с USE = gnome +media-libs/libcanberra -gnome sound + +media-plugins/grilo-plugins gnome-online-accounts +sys-auth/polkit gtk +sys-auth/pambase gnome-keyring +sys-apps/gnome-disk-utility gnome +app-cdr/brasero nautilus tracker +app-arch/file-roller nautilus +app-text/evince gnome gnome-keyring nautilus +app-admin/system-config-printer gnome-keyring +virtual/notification-daemon gnome + +# For game +sys-kernel/calculate-sources fsync + diff --git a/profiles/CLDG/parent b/profiles/CLDG/parent new file mode 100644 index 0000000..f3229c5 --- /dev/null +++ b/profiles/CLDG/parent @@ -0,0 +1 @@ +.. diff --git a/profiles/arch.list b/profiles/arch.list new file mode 100644 index 0000000..21d5bd8 --- /dev/null +++ b/profiles/arch.list @@ -0,0 +1 @@ +amd64 diff --git a/profiles/calculate.env b/profiles/calculate.env new file mode 100644 index 0000000..9bc8fa8 --- /dev/null +++ b/profiles/calculate.env @@ -0,0 +1,7 @@ +[main] +cl_template_location = calculate,distros,gnome-distro,local +cl_template_path = /var/db/repos/calculate/profiles/templates,/var/db/repos/distros/profiles/templates,/var/db/repos/gnome-distro/profiles/templates,/var/calculate/templates + +[update] +cl_update_rep_name = gentoo,calculate,distros,gnome-distro +cl_update_rep_url = https://git.calculate-linux.org/calculate/gentoo-overlay,https://git.calculate-linux.org/calculate/calculate-overlay,https://git.calculate-linux.org/calculate/distros-overlay,https://disk.yandex.ru/d/A1EbLu_OvbGxdg diff --git a/profiles/profiles.desc b/profiles/profiles.desc new file mode 100644 index 0000000..4b7220b --- /dev/null +++ b/profiles/profiles.desc @@ -0,0 +1,13 @@ +############################################# +# This is a list of valid profiles for each architecture. This file is used by +# repoman when doing a repoman scan or repoman full. +# DO NOT ADD PROFILES WITH A "die" or "exit" IN THEM OR IT KILLS REPOMAN +# +#layout: +#arch profile_directory status + + +# AMD64 Profiles +amd64 CLDG/amd64/20 stable + +# vim: set ts=8 diff --git a/profiles/repo_name b/profiles/repo_name new file mode 100644 index 0000000..24274af --- /dev/null +++ b/profiles/repo_name @@ -0,0 +1 @@ +gnome-distro diff --git a/profiles/templates/2_ac_install_merge/.calculate_directory b/profiles/templates/2_ac_install_merge/.calculate_directory new file mode 100644 index 0000000..6aa2084 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip env=install ac_install_merge==on diff --git a/profiles/templates/2_ac_install_merge/Depends/.calculate_directory b/profiles/templates/2_ac_install_merge/Depends/.calculate_directory new file mode 100644 index 0000000..dfccc15 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/Depends/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip cl_merge_pkg!= diff --git a/profiles/templates/2_ac_install_merge/Depends/gdm b/profiles/templates/2_ac_install_merge/Depends/gdm new file mode 100644 index 0000000..8c5cb09 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/Depends/gdm @@ -0,0 +1 @@ +# Calculate append=skip merge(gnome-base/gdm)!= merge=gui-libs/display-manager-init diff --git a/profiles/templates/2_ac_install_merge/README-eng.txt b/profiles/templates/2_ac_install_merge/README-eng.txt new file mode 100644 index 0000000..92d938f --- /dev/null +++ b/profiles/templates/2_ac_install_merge/README-eng.txt @@ -0,0 +1,13 @@ +# Calculate append=skip + +The ac_install_merge event: +- package installation +- package removal +- system setup* +- system installation +- Portages syncing + +*When cl-setup-system is run with the defaul '--live=off' option. + +Action: package configuration +env: install diff --git a/profiles/templates/2_ac_install_merge/README-rus.txt b/profiles/templates/2_ac_install_merge/README-rus.txt new file mode 100644 index 0000000..d1af3c7 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/README-rus.txt @@ -0,0 +1,13 @@ +# Calculate append=skip + +Событие ac_install_merge: +- установка пакета +- удаление пакета +- настройка системы* +- установка системы +- обновление портежей + +*При выполнении команды cl-setup-system со значением по умолчанию '--live=off'. + +Действие: настройка пакета +env: install \ No newline at end of file diff --git a/profiles/templates/2_ac_install_merge/gnome-base/.calculate_directory b/profiles/templates/2_ac_install_merge/gnome-base/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/.calculate_directory b/profiles/templates/2_ac_install_merge/gnome-base/gdm/.calculate_directory new file mode 100644 index 0000000..ec55664 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/.calculate_directory @@ -0,0 +1 @@ +# Calculate mergepkg()!= path=/etc name=pam.d diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/.calculate_directory b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/.calculate_directory new file mode 100644 index 0000000..5b53f75 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/etc/gdm diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/Default b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/Default new file mode 100644 index 0000000..3e7cbb9 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostLogin/Default @@ -0,0 +1,7 @@ +# Calculate append=replace chmod=0755 +#!/bin/sh +# PostLogin - + +#?pkg(sys-apps/calculate-utils:3[desktop])!=# +/usr/share/calculate/xdm/xdm --login +#pkg# diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/.calculate_directory b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/.calculate_directory new file mode 100644 index 0000000..5b53f75 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/etc/gdm diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/Default b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/Default new file mode 100644 index 0000000..83ca214 --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/PostSession/Default @@ -0,0 +1,7 @@ +# Calculate append=replace chmod=0755 +#!/bin/sh +# PostSession - + +#?pkg(sys-apps/calculate-utils:3[desktop])!=# +/usr/share/calculate/xdm/xdm --logout +#pkg# diff --git a/profiles/templates/2_ac_install_merge/gnome-base/gdm/gdm-launch-environment b/profiles/templates/2_ac_install_merge/gnome-base/gdm/gdm-launch-environment new file mode 100644 index 0000000..737891c --- /dev/null +++ b/profiles/templates/2_ac_install_merge/gnome-base/gdm/gdm-launch-environment @@ -0,0 +1,23 @@ +# Calculate +#%PAM-1.0 + +auth required pam_succeed_if.so audit quiet_success user = gdm +auth required pam_env.so +auth optional pam_permit.so + +account required pam_succeed_if.so audit quiet_success user = gdm +account optional pam_permit.so + +password required pam_deny.so + +session optional pam_loginuid.so +session optional pam_keyinit.so force revoke +session required pam_succeed_if.so audit quiet_success user = gdm + +session optional pam_permit.so +#?pkg(sys-apps/systemd)!=# +-session optional pam_systemd.so +#pkg# +#?pkg(sys-auth/elogind)!=# +-session optional pam_elogind.so +#pkg# diff --git a/profiles/templates/2_ac_install_merge/net-wireless/.calculate_directory b/profiles/templates/2_ac_install_merge/net-wireless/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/2_ac_install_merge/net-wireless/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/.calculate_directory b/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/.calculate_directory new file mode 100644 index 0000000..f08367b --- /dev/null +++ b/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/lib/udev name=rules.d mergepkg()!= diff --git a/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/61-gnome-bluetooth.rules b/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/61-gnome-bluetooth.rules new file mode 100644 index 0000000..b366b6d --- /dev/null +++ b/profiles/templates/2_ac_install_merge/net-wireless/gnome-bluetooth/61-gnome-bluetooth.rules @@ -0,0 +1,12 @@ +# Calculate +# Get access to /dev/rfkill for users +# See https://bugzilla.redhat.com/show_bug.cgi?id=514798 +# +# Updated for udev >= 154 +# http://bugs.debian.org/582188 +# https://bugzilla.redhat.com/show_bug.cgi?id=588660 + +ENV{ACL_MANAGE}=="0", GOTO="gnome_bluetooth_end" +ACTION!="add|change", GOTO="gnome_bluetooth_end" +KERNEL=="rfkill", GROUP="plugdev", MODE="0664", TAG+="udev-acl" +LABEL="gnome_bluetooth_end" diff --git a/profiles/templates/3_ac_install_live/.calculate_directory b/profiles/templates/3_ac_install_live/.calculate_directory new file mode 100644 index 0000000..7223aa3 --- /dev/null +++ b/profiles/templates/3_ac_install_live/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip env=install ac_install_live==on diff --git a/profiles/templates/3_ac_install_live/1-merge/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/.calculate_directory new file mode 100644 index 0000000..1480412 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/.calculate_directory @@ -0,0 +1 @@ +# Calculate mergepkg()!= path=/etc diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/0-custom.conf b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/0-custom.conf new file mode 100644 index 0000000..c1b7864 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/0-custom.conf @@ -0,0 +1,19 @@ +# Calculate pkg(sys-apps/calculate-utils:3[desktop])!= format=kde path=/etc/gdm name=custom.conf + +[daemon] +# Uncomment the line below to force the login screen to use Xorg +#WaylandEnable=false + +#?module(client)!=&&client.os_remote_auth!=# +AutomaticLoginEnable=false +AutomaticLogin= +#!module# +#?cl_autologin!=# +AutomaticLoginEnable=true +AutomaticLogin=#-cl_autologin-# +#!cl_autologin# +AutomaticLoginEnable=false +AutomaticLogin= +#cl_autologin# +#module# + diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/1-custom.conf b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/1-custom.conf new file mode 100644 index 0000000..db754fa --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/1-custom.conf @@ -0,0 +1,12 @@ +# Calculate format=raw path=/etc/gdm name=custom.conf append=after + +[security] + +[xdmcp] + +[chooser] + +[debug] +# Uncomment the line below to turn on debugging +#Enable=true + diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/.calculate_directory new file mode 100644 index 0000000..d75b705 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/.calculate_directory @@ -0,0 +1 @@ +# Calculate pkg(gnome-base/gnome-shell)>=40.0&&pkg(gnome-base/dconf)>=0.40.0 path=/etc/dconf diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm new file mode 100644 index 0000000..c151a9d Binary files /dev/null and b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm differ diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm.d/02-calculate-gdm-branding b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm.d/02-calculate-gdm-branding new file mode 100644 index 0000000..9ca1c53 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/db/gdm.d/02-calculate-gdm-branding @@ -0,0 +1,2 @@ +[org/gnome/login-screen] +logo='/usr/share/wallpapers/calculate-logo.png' diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/.calculate_directory new file mode 100644 index 0000000..d75b705 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/.calculate_directory @@ -0,0 +1 @@ +# Calculate pkg(gnome-base/gnome-shell)>=40.0&&pkg(gnome-base/dconf)>=0.40.0 path=/etc/dconf diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/gdm b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/gdm new file mode 100644 index 0000000..817afc5 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/profile/gdm @@ -0,0 +1,3 @@ +user-db:user +system-db:gdm +file-db:/usr/share/gdm/greeter-dconf-defaults diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/zzz-update-dconf b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/zzz-update-dconf new file mode 100644 index 0000000..b5b29c5 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/logo/zzz-update-dconf @@ -0,0 +1,6 @@ +# Calculate pkg(gnome-base/dconf)>=0.40.0 exec=/bin/bash + +# Обновление dconf +/usr/bin/dconf update + +true diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/.calculate_directory new file mode 100644 index 0000000..a079428 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/.calculate_directory @@ -0,0 +1 @@ +# Calculate pkg(gnome-base/gnome-shell)=>42.0,43.0 path=/usr/share/ diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/gnome-shell-theme.gresource b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/gnome-shell-theme.gresource new file mode 100644 index 0000000..beb71f1 Binary files /dev/null and b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/themes/dim-gray/gnome-shell/gnome-shell-theme.gresource differ diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/.calculate_directory new file mode 100644 index 0000000..65d4c03 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/usr/share name=wallpapers pkg(gnome-base/gdm)>=40.0 diff --git a/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/calculate-logo.png b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/calculate-logo.png new file mode 100644 index 0000000..6b40bb7 Binary files /dev/null and b/profiles/templates/3_ac_install_live/1-merge/gnome-base/gdm/wallpapers/calculate-logo.png differ diff --git a/profiles/templates/3_ac_install_live/1-merge/gui-libs/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gui-libs/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gui-libs/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/.calculate_directory new file mode 100644 index 0000000..637ef86 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/.calculate_directory @@ -0,0 +1,2 @@ +# Calculate mergepkg()!= name=etc + diff --git a/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/conf.d/display-manager b/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/conf.d/display-manager new file mode 100644 index 0000000..d914ace --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/gui-libs/display-manager-init/conf.d/display-manager @@ -0,0 +1,39 @@ +# Calculate comment=# + +CHECKVT=7 + +#?module(client)!=&&client.os_remote_auth!=# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#!module# +#?cl_autologin!=# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)==&&pkg(gnome-base/gdm)==# +XUSER=#-cl_autologin-# +DISPLAYMANAGER="bash" +START_STOP_ARGS="--background -- /usr/bin/xautologin $XUSER $CHECKVT" +#pkg# +#!cl_autologin# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#cl_autologin# +#module# diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/sys-apps/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/.calculate_directory new file mode 100644 index 0000000..38b058b --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/.calculate_directory @@ -0,0 +1,2 @@ +# Calculate mergepkg()!= append=skip + diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/.calculate_directory new file mode 100644 index 0000000..d032440 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/etc name=calculate diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/0-example b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/0-example new file mode 100644 index 0000000..8a06fba --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/0-example @@ -0,0 +1,18 @@ +# Calculate comment=# name=ini.env.example +#?os_install_locale_language==ru# +# Это файл настройки параметров шаблонов участвующих в настройке системы +# и профиля пользователя. +# +#os_install_locale_language# +#?os_install_locale_language!=ru# +# Any line which starts with a ; (semi-colon) or a # (hash) is a comment and +# is ignored. In this example we will use a # for commentry and a ; for parts +# of the config file that you may wish to enable +#os_install_locale_language# +#?os_install_locale_language==ru# +# Все строки, начинающиеся с ";" (точка с запятой) или "#" (хэш) являются +# комментариями, а # игнорируется. В этом примере мы будем использовать "#" +# для комментариев, а ";" для частей конфигурационного файла, которые вы +# можете включить +#os_install_locale_language# +# diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/1-example.system b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/1-example.system new file mode 100644 index 0000000..7acfec0 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/1-example.system @@ -0,0 +1,25 @@ +# Calculate comment=# name=ini.env.example append=after +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +#============================= System settings =============================== +#os_install_locale_language# +#?os_install_locale_language==ru# +#============================ Настройки системы ============================== +#os_install_locale_language# +#?os_install_locale_language==fr# +#============================ Paramètres système ============================= +#os_install_locale_language# +[system] +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Kernel and modules to be removed once sys-kernel/calculate-sources has been +# uninstalled +#os_install_locale_language# +#?os_install_locale_language==ru# +# Удалить ядро и модули при удалении пакета sys-kernel/calculate-sources +#os_install_locale_language# +#?os_install_locale_language==fr# +# Le noyau ainsi que les modules de celui-ci seront supprimés dès que le +# paquet sys-kernel/calculate-sources aura été installé +#os_install_locale_language# +; remove_old_kernel = on + + diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/2-example.theme b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/2-example.theme new file mode 100644 index 0000000..a6c4ce4 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/2-example.theme @@ -0,0 +1,324 @@ +# Calculate comment=# name=ini.env.example append=after +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +#============================== Theme settings =============================== +#os_install_locale_language# +#?os_install_locale_language==ru# +#============================== Настройки темы =============================== +#os_install_locale_language# +#?os_install_locale_language==fr# +#============================ Paramètres du thème ============================ +#os_install_locale_language# +[theme] + +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Authorization screen image. Preferred size 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображение экрана авторизации. Предпочтительный размер - 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==fr# +# Écran d’autorisation. Taille préférée : 4266x2048 +#os_install_locale_language# +; dm-login-background = /usr/share/themes/Calculate/dm-login.jpg + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Login screen image. Preferred size 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображение входа в сеанс. Предпочтительный размер - 4266х2048 +# 4266x2048. +#os_install_locale_language# +#?os_install_locale_language==fr# +# Écran d’identification. Taille préférée : 4266x2048 +#os_install_locale_language# +; dm-splash-background = /usr/share/themes/Calculate/dm-splash.jpg + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Background color on the login screen, if screen image not defined +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет фона во время входа в сеанс при отсутствии изображения +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur d’arrière-plan sur l’écran d’identification avec fond d’écran désactivé +#os_install_locale_language# +; dm-splash-color = 30648b + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Live USB boot menu screen +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображение меню Live USB +#os_install_locale_language# +#?os_install_locale_language==fr# +# Écran du menu Live USB +#os_install_locale_language# +; gfxboot-background = /usr/share/themes/Calculate/gfxboot.jpg + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Live USB menu selection color +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет выделения в меню Live USB +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur de sélection du menu Live USB +#os_install_locale_language# +; gfxboot-select-color = 461804 + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Live USB menu text color +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет текста в Live USB меню +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur de texte du menu Live USB +#os_install_locale_language# +; gfxboot-text-color = 958490 + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Live USB menu selected text color +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет выделенного текста в меню Live USB +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur du texte sélectionné du menu Live USB +#os_install_locale_language# +; gfxboot-text-highlight-color = fbcc89 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Calculate load screen image +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображения загрузчика системы +#os_install_locale_language# +#?os_install_locale_language==fr# +# Fond d’écran de chargement de Calculate +#os_install_locale_language# +; grub-background = /usr/share/themes/Calculate/grub.jpg + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Bootloader foreground/background text color if screen image defined. +# Accepted values: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет текста/фона загрузчика системы при наличии фонового изображения. +# Допустимые значения: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur de texte de premier plan / arrière-plan lors du chargement avec +# fond d’écran activé. Valeurs acceptées : 'black', 'blue', 'green', 'cyan', +# 'red', 'magenta', 'brown', 'light-gray', 'dark-gray', 'light-blue', +# 'light-green', 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +; grub-gfx-text-color = white/black + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Bootloader foreground/background selected text color if screen image +# defined. Accepted values: 'black', 'blue', 'green', 'cyan', 'red', +# 'magenta', 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет выделенного текста/фона загрузчика системы при наличии фонового +# изображения. +# Допустимые значения: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur du texte sélectionné de premier plan / arrière-plan lors du +# chargement avec fond d’écran activé. Valeurs acceptées : 'black', 'blue', +# 'green', 'cyan', 'red', 'magenta', 'brown', 'light-gray', 'dark-gray', +# 'light-blue', 'light-green', 'light-cyan', 'light-red', 'light-magenta', +# 'yellow', 'white' +#os_install_locale_language# +; grub-gfx-text-highlight-color = black/light-gray + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Bootloader foreground/background text color if screen image not defined. +# Accepted values: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет текста/фона загрузчика системы при отсутствии фонового изображения. +# Допустимые значения: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur de texte de premier plan / arrière-plan lors du chargement avec +# fond d’écran désactivé. Valeurs acceptées : 'black', 'blue', 'green', +# 'cyan', 'red', 'magenta', 'brown', 'light-gray', 'dark-gray', 'light-blue', +# 'light-green', 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +; grub-text-color = white/black + +#in# +#?in(os_linux_pkglist, calculate)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Bootloader foreground/background selected text color if screen image not +# defined. Accepted values: 'black', 'blue', 'green', 'cyan', 'red', 'magenta', +# 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет выделенного текста/фона загрузчика системы при отсутствии фонового +# изображения. Допустимые значения: 'black', 'blue', 'green', 'cyan', 'red', +# 'magenta', 'brown', 'light-gray', 'dark-gray', 'light-blue', 'light-green', +# 'light-cyan', 'light-red', 'light-magenta', 'yellow', 'white' +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur du texte sélectionné de premier plan / arrière-plan lors du +# chargement avec fond d’écran désactivé. Valeurs acceptées : 'black', 'blue', +# 'green', 'cyan', 'red', 'magenta', 'brown', 'light-gray', 'dark-gray', +# 'light-blue', 'light-green', 'light-cyan', 'light-red', 'light-magenta', +# 'yellow', 'white' +#os_install_locale_language# +; grub-text-highlight-color = black/light-gray + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Desktop wallpaper. Preferred size 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображение рабочего стола. Предпочтительный размер - 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==fr# +# Fond d’écran utilisateur. Taille préférée : 4266x2048 +#os_install_locale_language# +; profile-background = /usr/share/themes/Calculate/wallpaper.jpg + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Vertical gradient begin color for shutdown screen +#os_install_locale_language# +#?os_install_locale_language==ru# +# Начальный цвет вертикального градиента, +# используемого для фона экрана завершения работы +#os_install_locale_language# +; splash-shutdown-background-color-begin = 000000 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Vertical gradient end color for shutdown screen +#os_install_locale_language# +#?os_install_locale_language==ru# +# Конечный цвет вертикального градиента, +# используемого для фона экрана завершения работы +#os_install_locale_language# +; splash-shutdown-background-color-end = 000000 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Shutdown screen image. Background image preferred size is 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==ru# +# Изображение для экрана завершения работы. +# Для фонового изображения предпочтительный размер - 4266x2048 +#os_install_locale_language# +; splash-shutdown-picture = /usr/share/themes/Calculate/splash-shutdown.jpg + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# The way to display the image for shutdown screen: +# 'logo' or 'background' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Способ отображения изображения для экрана завершения работы: +# логотип ('logo') или фоновое изображение ('background') +#os_install_locale_language# +; splash-shutdown-type = background + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Shutdown notification text color +#os_install_locale_language# +#?os_install_locale_language==ru# +# Цвет текста сообщения о завершении работы компьютера +#os_install_locale_language# +#?os_install_locale_language==fr# +# Couleur du texte de notification d'arrêt +#os_install_locale_language# +; splash-shutdown-text-color = ffff9c + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Vertical gradient begin color for boot screen +#os_install_locale_language# +#?os_install_locale_language==ru# +# Начальный цвет вертикального градиента, +# используемого для фона экрана загрузки системы +#os_install_locale_language# +; splash-silent-background-color-begin = 090500 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Vertical gradient end color for boot screen +#os_install_locale_language# +#?os_install_locale_language==ru# +# Конечный цвет вертикального градиента, +# используемого для фона экрана загрузки системы +#os_install_locale_language# +; splash-silent-background-color-end = 090500 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# Boot screen image. Background image preferred size is 4266x2048 +#os_install_locale_language# +#?os_install_locale_language==ru# +# Изображение для экрана загрузки системы. +# Для фонового изображения предпочтительный размер - 4266x2048 +#os_install_locale_language# +; splash-silent-picture = /usr/share/themes/Calculate/splash-silent.png + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru# +# The way to display the image for boot screen: +# 'logo' or 'background' +#os_install_locale_language# +#?os_install_locale_language==ru# +# Способ отображения изображения для экрана загрузки компьютера: +# логотип ('logo') или фоновое изображение ('background') +#os_install_locale_language# +; splash-silent-type = logo + +#in# diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/3-example.profile b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/3-example.profile new file mode 100644 index 0000000..56b76fa --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/3-example.profile @@ -0,0 +1,172 @@ +# Calculate comment=# name=ini.env.example append=after in(os_linux_pkglist,CLDG)!= +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +#=========================== User profile settings =========================== +#os_install_locale_language# +#?os_install_locale_language==ru# +#======================= Настройки профиля пользователя ====================== +#os_install_locale_language# +#?os_install_locale_language==fr# +#======================= Paramètres de profil utilisateur ==================== +#os_install_locale_language# +[profile] + +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Window border size +#os_install_locale_language# +#?os_install_locale_language==ru# +# Размер границы окна +#os_install_locale_language# +#?os_install_locale_language==fr# +# Épaisseur de la bordure des fenêtres +#os_install_locale_language# +; appearance-border = + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Mouse cursor theme +#os_install_locale_language# +#?os_install_locale_language==ru# +# Тема курсора мышки +#os_install_locale_language# +#?os_install_locale_language==fr# +# Thème du curseur de la souris +#os_install_locale_language# +; appearance-cursor = Calculate + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Icon theme +#os_install_locale_language# +#?os_install_locale_language==ru# +# Тема иконок +#os_install_locale_language# +#?os_install_locale_language==fr# +# Thème des icônes +#os_install_locale_language# +; appearance-icons = Calculate + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Look and feel +#os_install_locale_language# +#?os_install_locale_language==ru# +# Внешний вид +#os_install_locale_language# +#?os_install_locale_language==fr# +# Apparence +#os_install_locale_language# +; appearance-style = + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Desktop wallpaper. To change it, we recommended to use the parameters in +# the “theme” section +#os_install_locale_language# +#?os_install_locale_language==ru# +# Фоновое изображение рабочего стола. Рекомендуется менять обои при помощи +# настройки темы в секции "theme" +#os_install_locale_language# +#?os_install_locale_language==fr# +# Fond d’écran utilisateur. Il est recommandé d’utiliser les réglages +# appropriés de la section “thème” pour changer de fond d’écran +#os_install_locale_language# +; appearance-wallpaper = + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Font size +#os_install_locale_language# +#?os_install_locale_language==ru# +# Размер шрифта +#os_install_locale_language# +#?os_install_locale_language==fr# +# Taille de la police +#os_install_locale_language# +; font-size = 10 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Keyboard delay (milliseconds) +#os_install_locale_language# +#?os_install_locale_language==ru# +# Задержка нажатия клавиш в миллисекундах +#os_install_locale_language# +#?os_install_locale_language==fr# +# Délai de frappe du clavier (millisecondes) +#os_install_locale_language# +; keyboard-delay = 330 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Keyboard repeat rate (characters per second) +#os_install_locale_language# +#?os_install_locale_language==ru# +# Частота повтора (знаков в секунду) +#os_install_locale_language# +#?os_install_locale_language==fr# +# Taux de répétition du clavier (caractères/sec) +#os_install_locale_language# +; keyboard-rate = 30 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Mouse click policy ('single' or 'double') +#os_install_locale_language# +#?os_install_locale_language==ru# +# Настройка клика мышки ('single' or 'double') +#os_install_locale_language# +#?os_install_locale_language==fr# +# Configuration du clic de la souris ('single' ou 'double') +#os_install_locale_language# +; mouse-clickpolicy = single + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Mouse double click delay (milliseconds) +#os_install_locale_language# +#?os_install_locale_language==ru# +# Задержка в миллисекундах двойного клика мышки +#os_install_locale_language# +#?os_install_locale_language==fr# +# Délai du double-clic (millisecondes) +#os_install_locale_language# +; mouse-doubleclick-delayed = 400 + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Left hand mouse configuration +#os_install_locale_language# +#?os_install_locale_language==ru# +# Настройка мышки для левшей. +#os_install_locale_language# +#?os_install_locale_language==fr# +# Configuration de la souris pour gaucher +#os_install_locale_language# +; mouse-lefthanded = off + +#in# +#?in(os_linux_pkglist, CLDG)!=# +#?os_install_locale_language!=ru&&os_install_locale_language!=fr# +# Time in seconds before the display is turned off when idle, '0' - never +#os_install_locale_language# +#?os_install_locale_language==ru# +# Время в секундах, после которого дисплей переходит в режим ожидания, '0' - +# никогда +#os_install_locale_language# +#?os_install_locale_language==fr# +# Mettre en veille après (secondes), '0', ne jamais arrêter +#os_install_locale_language# +; power-display-sleep = 16 + +#in# diff --git a/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/4-example.container b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/4-example.container new file mode 100644 index 0000000..ce2f6d8 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/sys-apps/calculate-utils/ini.example/4-example.container @@ -0,0 +1,36 @@ +# Calculate comment=# name=ini.env.example append=after ini(container.type)==desktop +#?os_install_locale_language!=ru# +#============================= Xorg settings =============================== +#os_install_locale_language# +#?os_install_locale_language==ru# +#============================ Настройки Xorg ============================== +#os_install_locale_language# +[xorg] +#?os_install_locale_language!=ru# +# virtual terminal number +#os_install_locale_language# +#?os_install_locale_language==ru# +# номер виртуального терминала +#os_install_locale_language# +; vt = 7 +#?os_install_locale_language!=ru# +# bus id for isolate video device +#os_install_locale_language# +#?os_install_locale_language==ru# +# идентификатор шины для изолирования видеокарты +#os_install_locale_language# +; busid = PCI:0:0:2:0 +#?os_install_locale_language!=ru# +# `on` for disable virtual terminal switching +#os_install_locale_language# +#?os_install_locale_language==ru# +# `on` для отключения возможности переключать виртуальные терминалы +#os_install_locale_language# +; sharevts = off +#?os_install_locale_language!=ru# +# multiuser mode +#os_install_locale_language# +#?os_install_locale_language==ru# +# многопользователейский режим +#os_install_locale_language# +; multiuser = on diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/x11-base/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/.calculate_directory new file mode 100644 index 0000000..637ef86 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/.calculate_directory @@ -0,0 +1,2 @@ +# Calculate mergepkg()!= name=etc + diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/.calculate_directory new file mode 100644 index 0000000..11ffb10 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/.calculate_directory @@ -0,0 +1 @@ +# Calculate pkg(x11-base/xorg-server)<1.20.10-r3 diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/xdm b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/xdm new file mode 100644 index 0000000..d914ace --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/conf.d/xdm @@ -0,0 +1,39 @@ +# Calculate comment=# + +CHECKVT=7 + +#?module(client)!=&&client.os_remote_auth!=# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#!module# +#?cl_autologin!=# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)==&&pkg(gnome-base/gdm)==# +XUSER=#-cl_autologin-# +DISPLAYMANAGER="bash" +START_STOP_ARGS="--background -- /usr/bin/xautologin $XUSER $CHECKVT" +#pkg# +#!cl_autologin# +#?pkg(gnome-base/gdm)!=# +DISPLAYMANAGER="gdm" +START_STOP_ARGS= +#pkg# +#?pkg(x11-misc/lightdm)!=&&pkg(gnome-base/gdm)==# +DISPLAYMANAGER="lightdm" +START_STOP_ARGS= +#pkg# +#cl_autologin# +#module# diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/.calculate_directory new file mode 100644 index 0000000..bed8108 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/.calculate_directory @@ -0,0 +1 @@ +# Calculate cl_ver>=3.5.2.21 append=skip diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome.xml b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome.xml new file mode 100644 index 0000000..9ff0593 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome.xml @@ -0,0 +1,97 @@ +# Calculate path=/usr/share/gnome-background-properties name=calculate-gnome.xml pkg(gnome-base/gnome-session)!= + + + +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 11 Blue.jpg)!=&&exists(/usr/share/backgrounds/calculate/Calculate Linux 11 Brown.jpg)!=# + + Calculate Linux 11 Blue_Brown + /usr/share/backgrounds/calculate/Calculate Linux 11 Blue.jpg + /usr/share/backgrounds/calculate/Calculate Linux 11 Brown.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 12 Blue.jpg)!=&&exists(/usr/share/backgrounds/calculate/Calculate Linux 12 Brown.jpg)!=# + + Calculate Linux 12 Blue_Brown + /usr/share/backgrounds/calculate/Calculate Linux 12 Blue.jpg + /usr/share/backgrounds/calculate/Calculate Linux 12 Brown.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 13 Green.jpg)!=&&exists(/usr/share/backgrounds/calculate/Calculate Linux 13 Magenta.jpg)!=# + + Calculate Linux 13 Green_Magenta + /usr/share/backgrounds/calculate/Calculate Linux 13 Green.jpg + /usr/share/backgrounds/calculate/Calculate Linux 13 Magenta.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 13 Blue.jpg)!=&&exists(/usr/share/backgrounds/calculate/Calculate Linux 13 Brown.jpg)!=# + + Calculate Linux 13 Blue_Brown + /usr/share/backgrounds/calculate/Calculate Linux 13 Blue.jpg + /usr/share/backgrounds/calculate/Calculate Linux 13 Brown.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 14.jpg)!=# + + Calculate Linux 14 + /usr/share/backgrounds/calculate/Calculate Linux 14.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 15.jpg)!=# + + Calculate Linux 15 + /usr/share/backgrounds/calculate/Calculate Linux 15.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux 17.jpg)!=# + + Calculate Linux 17 + /usr/share/backgrounds/calculate/Calculate Linux 17.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# +#?exists(/usr/share/backgrounds/calculate/Calculate Linux.jpg)!=# + + Calculate Linux + /usr/share/backgrounds/calculate/Calculate Linux.jpg + zoom + solid + #000000 + #000000 + Calculate Ltd. http://www.calculate-linux.org + +#exists# + diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/.calculate_directory b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/.calculate_directory new file mode 100644 index 0000000..3c97142 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/usr/share/backgrounds name=calculate pkg(gnome-base/gnome-session)!= diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Blue.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Blue.jpg new file mode 100644 index 0000000..ac90a76 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Blue.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_11_Blue/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Brown.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Brown.jpg new file mode 100644 index 0000000..75cb5f3 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 11 Brown.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_11_Brown/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Blue.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Blue.jpg new file mode 100644 index 0000000..08f639d --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Blue.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_12_Blue/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Brown.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Brown.jpg new file mode 100644 index 0000000..317a5d5 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 12 Brown.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_12_Brown/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Blue.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Blue.jpg new file mode 100644 index 0000000..3b99204 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Blue.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_13_Blue/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Brown.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Brown.jpg new file mode 100644 index 0000000..79203a0 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Brown.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_13_Brown/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Green.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Green.jpg new file mode 100644 index 0000000..1eeca66 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Green.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_13_Green/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Magenta.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Magenta.jpg new file mode 100644 index 0000000..373da16 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 13 Magenta.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_13_Magenta/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 14.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 14.jpg new file mode 100644 index 0000000..9b24cc1 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 14.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_14/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 15.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 15.jpg new file mode 100644 index 0000000..c91d912 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 15.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_15/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 17.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 17.jpg new file mode 100644 index 0000000..cddbb93 --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux 17.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux_17/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux.jpg b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux.jpg new file mode 100644 index 0000000..28cf10c --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate-gnome/Calculate Linux.jpg @@ -0,0 +1 @@ +# Calculate link=#-wallpaper(#-os_install_x11_resolution-#,/usr/share/wallpapers/Calculate_Linux/contents/images)-# mirror diff --git a/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate.xml.remove b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate.xml.remove new file mode 100644 index 0000000..d8ca2ad --- /dev/null +++ b/profiles/templates/3_ac_install_live/1-merge/x11-base/xorg-server/wallpapers/calculate.xml.remove @@ -0,0 +1 @@ +# Calculate path=/usr/share/gnome-background-properties name=calculate.xml append=remove diff --git a/profiles/templates/3_ac_install_live/Depends/gdm b/profiles/templates/3_ac_install_live/Depends/gdm new file mode 100644 index 0000000..e982297 --- /dev/null +++ b/profiles/templates/3_ac_install_live/Depends/gdm @@ -0,0 +1 @@ +# Calculate append=skip merge(gnome-base/gdm)!= merge=x11-base/xorg-server diff --git a/profiles/templates/3_ac_install_live/README-eng.txt b/profiles/templates/3_ac_install_live/README-eng.txt new file mode 100644 index 0000000..7380711 --- /dev/null +++ b/profiles/templates/3_ac_install_live/README-eng.txt @@ -0,0 +1,15 @@ +# Calculate append=skip + +The ac_install_live event: +- package installation (not chroot*) +- package removal (not chroot) +- system setup +- system installation +- first boot + + +*The event will not be used while the system is being built or if the package +is being installed in builder mode. + +Action: package configuration +env: install diff --git a/profiles/templates/3_ac_install_live/README-rus.txt b/profiles/templates/3_ac_install_live/README-rus.txt new file mode 100644 index 0000000..ac6202b --- /dev/null +++ b/profiles/templates/3_ac_install_live/README-rus.txt @@ -0,0 +1,14 @@ +# Calculate append=skip + +Событие ac_install_live: +- установка пакета (не chroot*) +- удаление пакета (не chroot) +- настройка системы +- установка системы +- первая загрузка + +*Событие не будет использоваться во время сборки системы или установке пакета +в builder-режиме. + +Действие: настройка пакета +env: install \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/.calculate_directory b/profiles/templates/6_ac_desktop_profile/.calculate_directory new file mode 100644 index 0000000..0af99e1 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/.calculate_directory @@ -0,0 +1 @@ +# Calculate env=desktop path=~ name= chown=#-main.ur_login-#:#-main.ur_group-# ac_desktop_profile==on diff --git a/profiles/templates/6_ac_desktop_profile/2-user/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/.calculate_directory new file mode 100644 index 0000000..6e56023 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip ur_login!=root&&ini(main.update)!=off diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/.calculate_directory new file mode 100644 index 0000000..720d52e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.cache/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.cache/.calculate_directory new file mode 100644 index 0000000..a36b2fb --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.cache/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=~/ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.calculate_directory new file mode 100644 index 0000000..f956fac --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip mergepkg(gnome-base/gnome-session)>=40.0&&ini(update.gnome)!=off&&ini(ver.gnome)==&&exists(~/.config/gnome-session)== diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/.calculate_directory new file mode 100644 index 0000000..879d998 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/.calculate_directory @@ -0,0 +1 @@ +# Calculate name= path="#-ini(resource.desktop)-#" diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/FTP.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/FTP.desktop new file mode 100644 index 0000000..b3eb71d --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/FTP.desktop @@ -0,0 +1,9 @@ +# Calculate chmod=755 format=kde env(client.os_remote_auth)!=&&ur_domain_set==on&&server(ftp.host)!= +[Desktop Entry] +Version=1.0 +Name=FTP +Comment=Open FTP network folder +Comment[ru_RU]=Открыть сетевой диск FTP +Icon=folder-download +URL=file:////home/#-ur_login-#/FTP +Type=Link diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Home.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Home.desktop new file mode 100644 index 0000000..0d16e32 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Home.desktop @@ -0,0 +1,9 @@ +# Calculate chmod=755 format=kde env(client.os_remote_auth)!=&&ur_domain_set==on append=replace +[Desktop Entry] +Version=1.0 +Name=Home +Comment=Open home network folder +Comment[ru_RU]=Открыть сетевой диск с личными файлами +Icon=user-home +URL=file:////home/#-ur_login-#/Home +Type=Link diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/README.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/README.desktop new file mode 100644 index 0000000..e34c77f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/README.desktop @@ -0,0 +1,28 @@ +# Calculate chmod=755 os_root_type==livecd +#!/usr/bin/env xdg-open + +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Type=Application +Name[bg]=Ръководство за инсталиране +Name[ru]=Руководство по установке +Name=Installation Guide +Comment= +Categories=Application; +#?os_locale_language!=ru# +#?pkg(www-client/chromium)!=# +Exec=chromium --app="file:///usr/share/calculate/doc/handbook-en.html" +#!pkg# +Exec=xdg-open /usr/share/calculate/doc/handbook-en.html +#pkg# +#!os_locale_language# +#?pkg(www-client/chromium)!=# +Exec=chromium --app="file:///usr/share/calculate/doc/handbook-ru.html" +#!pkg# +Exec=xdg-open /usr/share/calculate/doc/handbook-ru.html +#pkg# +#os_locale_language# +Icon=help-contents +Terminal=false +StartupNotify=false diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Share.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Share.desktop new file mode 100644 index 0000000..ada005b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/Share.desktop @@ -0,0 +1,9 @@ +# Calculate chmod=755 format=kde env(client.os_remote_auth)!=&&ur_domain_set==on +[Desktop Entry] +Version=1.0 +Name=Share +Comment=Open share network folder +Comment[ru_RU]=Открыть сетевой диск с сетевыми ресурсами +Icon=folder-remote +URL=file:////home/#-ur_login-#/Share +Type=Link diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-community.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-community.desktop new file mode 100644 index 0000000..c58ec74 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-community.desktop @@ -0,0 +1 @@ +# Calculate chmod=755 format=kde link=/usr/share/applications/calculate-chat.desktop mirror os_root_type==livecd diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-install.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-install.desktop new file mode 100644 index 0000000..b65a600 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/Desktop/calculate-install.desktop @@ -0,0 +1,3 @@ +# Calculate chmod=755 format=kde link=/usr/share/applications/cl-console-gui-install.desktop os_root_type==livecd mirror +[Desktop Entry] +NoDisplay=false diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/.calculate_directory new file mode 100644 index 0000000..03067b0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=~/.local/share diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui-update.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui-update.desktop new file mode 100644 index 0000000..8ee566d --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui-update.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Calculate Linux Update +Name[ru]=Обновление Calculate Linux +Comment=Calculate Linux updater +Exec=cl-console-gui-update +Icon=console-gui-update +Terminal=false +Type=Application +Categories=Settings;X-GNOME-PersonalSettings; +OnlyShowIn=KDE;LXQt;LXDE;MATE;Razor;ROX;TDE;Unity;XFCE;Old;GNOME +StartupNotify=true diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui.desktop b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui.desktop new file mode 100644 index 0000000..658c62f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/applications/cl-console-gui.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=Calculate Console +Name[ru]=Консоль Calculate +Comment=Calculate Console +Exec=cl-console-gui +Icon=cl-console-gui +Terminal=false +Type=Application +Categories=Settings;X-GNOME-PersonalSettings; +OnlyShowIn=KDE;LXQt;LXDE;MATE;Razor;ROX;TDE;Unity;XFCE;Old;GNOME diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/.calculate_directory new file mode 100644 index 0000000..03067b0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=~/.local/share diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/SystemSettings.directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/SystemSettings.directory new file mode 100644 index 0000000..a416a7a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/desktop-directories/SystemSettings.directory @@ -0,0 +1,12 @@ +[Desktop Entry] +Name[en_CA]=Settings +Name[en_GB]=Settings +Name[ru]=Параметры +Name=Settings +Comment[en_CA]=Calculate system parameters +Comment[en_GB]=Calculate system parameters +Comment[ru]=Параметры системы Calculate +Comment=Calculate system parameters +# Translators: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=gnome-settings +Type=Directory diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/.calculate_directory b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/.calculate_directory new file mode 100644 index 0000000..f7b3472 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=~/.local/share/gnome-shell diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/LICENSE b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/LICENSE new file mode 100644 index 0000000..be85d4e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/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. + + Just Perfection GNOME Shell Desktop + Copyright (C) 2021 Javad Rahmatzadeh + + 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: + + Just Perfection GNOME Shell Desktop Copyright (C) 2021 Javad Rahmatzadeh + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/extension.js new file mode 100644 index 0000000..2197908 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/extension.js @@ -0,0 +1,546 @@ +/** + * Shutdown Timer Extension for GNOME Shell + * + * @author Deminder + * @author D. Neumann + * @copyright 2014-2021 + * @license GNU General Public License v3.0 + */ +/* exported init, enable, disable */ + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { + ScheduleInfo, + MenuItem, + Textbox, + RootMode, + Timer, + Convenience, + EndSessionDialogAware, + SessionModeAware, + CheckCommand, +} = Me.imports.lib; + +const { + guiIdle, + throttleTimeout, + disableGuiIdle, + modeLabel, + enableGuiIdle, + longDurationString, + logDebug, +} = Convenience; + +/* IMPORTS */ +const { GLib } = imports.gi; +const LoginManager = imports.misc.loginManager; + +// screen and main functionality +const Main = imports.ui.main; +const PopupMenu = imports.ui.popupMenu; + +// translations +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; +const C_ = Gettext.pgettext; +const _n = Gettext.ngettext; + +/* GLOBAL VARIABLES */ +let shutdownTimerMenu, timer, separator, settings; + +let initialized = false; + +/** + * + */ +function refreshExternalInfo() { + if (shutdownTimerMenu !== undefined) { + shutdownTimerMenu.infoFetcher.refresh(); + } +} + +/** + * + * @param textmsg + */ +function maybeShowTextbox(textmsg) { + if (settings.get_boolean('show-textboxes-value')) { + guiIdle(() => { + Textbox.showTextbox(textmsg); + }); + } +} + +/** + * + * @param info + * @param stopScheduled + */ +async function maybeStopRootModeProtection(info, stopScheduled = false) { + if ( + (stopScheduled || !info.scheduled) && + settings.get_boolean('root-mode-value') + ) { + logDebug(`Stop root mode protection for: ${info.mode}`); + try { + switch (info.mode) { + case 'poweroff': + case 'reboot': + await RootMode.shutdownCancel(); + refreshExternalInfo(); + break; + default: + logDebug(`No root mode protection stopped for: ${info.mode}`); + } + } catch (err) { + maybeShowTextbox( + C_('Error', '%s\n%s').format(_('Root mode protection failed!'), err) + ); + logError(err, 'DisableRootModeProtection'); + } + } +} + +/** + * + * Insure that shutdown is executed even if the GLib timer fails by running + * the `shutdown` command delayed by 1 minute. Suspend is not insured. + * + * @param info + */ +async function maybeStartRootModeProtection(info) { + if (info.scheduled && settings.get_boolean('root-mode-value')) { + logDebug(`Start root mode protection for: ${info.label}`); + try { + const minutes = Math.max(0, info.minutes) + 1; + switch (info.mode) { + case 'poweroff': + await RootMode.shutdown(minutes); + refreshExternalInfo(); + break; + case 'reboot': + await RootMode.shutdown(minutes, true); + refreshExternalInfo(); + break; + default: + logDebug(`No root mode protection started for: ${info.mode}`); + } + } catch (err) { + maybeShowTextbox( + C_('Error', '%s\n%s').format(_('Root mode protection failed!'), err) + ); + logError(err, 'EnableRootModeProtection'); + } + } +} + +/** + * + * @param wakeMinutes + */ +async function maybeStartWake(wakeMinutes) { + if (settings.get_boolean('auto-wake-value')) { + await wakeAction('wake', wakeMinutes); + } +} + +/** + * + */ +async function maybeStopWake() { + if (settings.get_boolean('auto-wake-value')) { + await wakeAction('no-wake'); + } +} + +// timer action (shutdown/reboot/suspend) +/** + * + * @param mode + */ +async function serveInernalSchedule(mode) { + const checkCmd = maybeCheckCmdString(); + try { + if (checkCmd !== '') { + guiIdle(() => { + shutdownTimerMenu.checkRunning = true; + shutdownTimerMenu.updateShutdownInfo(); + }); + maybeShowTextbox(checkCmd); + maybeShowTextbox( + _('Waiting for %s confirmation').format(modeLabel(mode)) + ); + await CheckCommand.doCheck( + checkCmd, + line => { + if (!line.startsWith('[')) { + maybeShowTextbox(`'${line}'`); + } + }, + async () => { + // keep protection alive + await maybeStartRootModeProtection( + new ScheduleInfo.ScheduleInfo({ mode, deadline: 0 }) + ); + } + ); + } + // check succeeded: do shutdown + shutdown(mode); + } catch (err) { + logError(err, 'CheckError'); + // check failed: cancel shutdown + // stop root protection + await maybeStopRootModeProtection( + new ScheduleInfo.ScheduleInfo({ mode, deadline: 0 }), + true + ); + try { + const root = settings.get_boolean('root-mode-value'); + if (root) { + await RootMode.shutdownCancel(); + } + const wake = settings.get_boolean('auto-wake-value'); + if (wake) { + await RootMode.wakeCancel(); + } + if (root || wake) { + refreshExternalInfo(); + } + } catch (err2) { + // error is most likely: script not installed + logError(err2, 'CheckError'); + } + // check failed: log failure + let code = '?'; + if ('code' in err) { + code = `${err.code}`; + logDebug(`Check command aborted ${mode}. Code: ${code}`); + } + maybeShowTextbox( + C_('CheckCommand', '%s aborted (Code: %s)').format(modeLabel(mode), code) + ); + if (parseInt(code) === 19) { + maybeShowTextbox(_('Confirmation canceled')); + } + } finally { + // update shutdownTimerMenu + guiIdle(() => { + shutdownTimerMenu.checkRunning = false; + shutdownTimerMenu.updateShutdownInfo(); + }); + // reset schedule timestamp + settings.set_int('shutdown-timestamp-value', -1); + } +} + +/** + * + */ +function foregroundActive() { + // ubuntu22.04 uses 'ubuntu' as 'user' sessionMode + return Main.sessionMode.currentMode !== 'unlock-dialog'; +} + +/** + * + * @param mode + */ +function shutdown(mode) { + if (foregroundActive()) { + Main.overview.hide(); + Textbox.hideAll(); + } + + if (['reboot', 'poweroff'].includes(mode)) { + if ( + foregroundActive() && + settings.get_boolean('show-end-session-dialog-value') + ) { + // show endSessionDialog + // refresh root shutdown protection + maybeStartRootModeProtection( + new ScheduleInfo.ScheduleInfo({ mode, deadline: 0 }) + ); + EndSessionDialogAware.register(); + const session = new imports.misc.gnomeSession.SessionManager(); + if (mode === 'reboot') { + session.RebootRemote(0); + } else { + session.ShutdownRemote(0); + } + } else { + imports.misc.util.spawnCommandLine( + mode === 'reboot' ? 'reboot' : 'poweroff' + ); + } + } else if (mode === 'suspend') { + LoginManager.getLoginManager().suspend(); + } else { + logError(new Error(`Unknown shutdown mode: ${mode}`)); + } +} + +/* ACTION FUNCTIONS */ +/** + * + * @param mode + * @param minutes + */ +async function wakeAction(mode, minutes) { + try { + switch (mode) { + case 'wake': + await RootMode.wake(minutes); + refreshExternalInfo(); + return; + case 'no-wake': + await RootMode.wakeCancel(); + refreshExternalInfo(); + return; + default: + logError(new Error(`Unknown wake mode: ${mode}`)); + return; + } + } catch (err) { + maybeShowTextbox( + C_('Error', '%s\n%s').format(_('Wake action failed!'), err) + ); + } +} + +/** + * + * @param stopProtection + */ +function stopSchedule(stopProtection = true) { + EndSessionDialogAware.unregister(); + const canceled = CheckCommand.maybeCancel(); + if (!canceled && settings.get_int('shutdown-timestamp-value') > -1) { + settings.set_int('shutdown-timestamp-value', -1); + maybeShowTextbox(_('Shutdown Timer stopped')); + } + + if (stopProtection) { + // stop root protection + const info = + timer !== undefined ? timer.info : new ScheduleInfo.ScheduleInfo(); + return Promise.all([maybeStopRootModeProtection(info), maybeStopWake()]); + } + return Promise.resolve(); +} + +/** + * + * @param maxTimerMinutes + * @param wakeMinutes + */ +async function startSchedule(maxTimerMinutes, wakeMinutes) { + EndSessionDialogAware.unregister(); + CheckCommand.maybeCancel(); + + const seconds = maxTimerMinutes * 60; + const info = new ScheduleInfo.ScheduleInfo({ + mode: settings.get_string('shutdown-mode-value'), + deadline: GLib.DateTime.new_now_utc().to_unix() + Math.max(1, seconds), + }); + settings.set_int('shutdown-timestamp-value', info.deadline); + let startPopupText = C_('StartSchedulePopup', '%s in %s').format( + modeLabel(info.mode), + longDurationString( + maxTimerMinutes, + h => _n('%s hour', '%s hours', h), + m => _n('%s minute', '%s minutes', m) + ) + ); + const checkCmd = maybeCheckCmdString(); + if (checkCmd !== '') { + maybeShowTextbox(checkCmd); + } + maybeShowTextbox(startPopupText); + + // start root protection + await Promise.all([ + maybeStartRootModeProtection(info), + maybeStartWake(wakeMinutes), + ]); +} + +/** + * + */ +function maybeCheckCmdString() { + const cmd = settings + .get_string('check-command-value') + .split('\n') + .filter(line => !line.trimLeft().startsWith('#') && line.trim()) + .join('\n'); + + return settings.get_boolean('enable-check-command-value') ? cmd : ''; +} + +/** + * + * @param info + */ +function onShutdownScheduleChange(info) { + if (timer !== undefined) { + timer.adjustTo(info); + } +} + +/** + * + * @param sessionMode + */ +function onSessionModeChange(sessionMode) { + logDebug(`sessionMode: ${sessionMode}`); + switch (sessionMode) { + case 'unlock-dialog': + disableForeground(); + break; + case 'user': + default: + enableForeground(); + break; + } +} + +/** + * + */ +function enableForeground() { + enableGuiIdle(); + // add separator line and submenu in status area menu + const statusMenu = Main.panel.statusArea['aggregateMenu']; + if (separator === undefined) { + separator = new PopupMenu.PopupSeparatorMenuItem(); + statusMenu.menu.addMenuItem(separator); + } + if (shutdownTimerMenu === undefined) { + shutdownTimerMenu = new MenuItem.ShutdownTimer(); + shutdownTimerMenu.checkRunning = CheckCommand.isChecking(); + timer.setTickCallback( + shutdownTimerMenu.updateShutdownInfo.bind(shutdownTimerMenu) + ); + statusMenu.menu.addMenuItem(shutdownTimerMenu); + } + // stop schedule if endSessionDialog cancel button is activated + EndSessionDialogAware.load(stopSchedule); + logDebug('Enabled foreground.'); +} + +/** + * + */ +function disableForeground() { + disableGuiIdle(); + Textbox.hideAll(); + if (shutdownTimerMenu !== undefined) { + shutdownTimerMenu.destroy(); + if (timer !== undefined) { + timer.setTickCallback(null); + // keep sleep process alive + timer.stopForeground(); + } + } + shutdownTimerMenu = undefined; + if (separator !== undefined) { + separator.destroy(); + } + separator = undefined; + EndSessionDialogAware.unload(); + logDebug('Disabled foreground.'); +} + +/* EXTENSION MAIN FUNCTIONS */ +/** + * + */ +function init() { + // initialize translations + ExtensionUtils.initTranslations(); +} + +let throttleDisable = null; +let throttleDisableCancel = null; + +/** + * + */ +function enable() { + if (!initialized) { + [throttleDisable, throttleDisableCancel] = throttleTimeout( + completeDisable, + 100 + ); + // initialize settings + settings = ExtensionUtils.getSettings(); + // ensure that no shutdown is scheduled + settings.set_int('shutdown-timestamp-value', -1); + MenuItem.init(settings, { + wakeAction, + startSchedule, + stopSchedule, + maybeStopRootModeProtection, + maybeStartRootModeProtection, + onShutdownScheduleChange, + }); + Textbox.init(); + + // check for shutdown may run in background and can be canceled by user + // starts internal shutdown schedule if ready + timer = new Timer.Timer(serveInernalSchedule); + + SessionModeAware.load(onSessionModeChange); + + initialized = true; + } else { + throttleDisableCancel(); + } + if (foregroundActive()) { + enableForeground(); + logDebug('Completly enabled.'); + } else { + logDebug('Background enabled.'); + } +} + +/** + * + */ +function disable() { + // unlock-dialog session-mode is required such that the timer action can trigger + disableForeground(); + // DELAYED DISABLE: + // Workaround for Gnome 42 weird behaviour (?unlock-dialog sessionMode bug?): + // on first screensaver activation after login gnome-shell quickly enables/disables this extension + // for each extension that is also enabled besides this extension + if (initialized) { + throttleDisable(); + } +} + +/** + * + */ +function completeDisable() { + if (initialized) { + if (timer !== undefined) { + timer.stopTimer(); + timer = undefined; + } + Textbox.uninit(); + MenuItem.uninit(); + // clear internal schedule and keep root protected schedule + stopSchedule(false); + SessionModeAware.unload(); + + throttleDisableCancel(); + throttleDisable = null; + throttleDisableCancel = null; + initialized = false; + logDebug('Completly disabled.'); + } +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/icons/shutdown-timer-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/icons/shutdown-timer-symbolic.svg new file mode 100644 index 0000000..8e85029 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/icons/shutdown-timer-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/CheckCommand.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/CheckCommand.js new file mode 100644 index 0000000..9e684f4 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/CheckCommand.js @@ -0,0 +1,95 @@ +/** + * CheckCommand module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported doCheck, maybeCancel, isChecking */ +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { RootMode, Convenience } = Me.imports.lib; +const Gio = imports.gi.Gio; +const logDebug = Convenience.logDebug; + +let checkCancel; + +/** + * Wait for checkCmd to execute successfully. + * + * @param {string} checkCmd check command + * @param {(line: string) => void} onLog + * @param {async () => void} redoRootProtection + */ +function doCheck(checkCmd, onLog, redoRootProtection) { + if (checkCancel !== undefined) { + return Promise.reject( + new Error( + 'Confirmation canceled: attempted to start a second check command!' + ) + ); + } + + checkCancel = new Gio.Cancellable(); + const checkWatchCancel = new Gio.Cancellable(); + return Promise.all([ + _doCheck(checkCmd, checkWatchCancel, onLog), + continueRootProtectionDuringCheck(checkWatchCancel, redoRootProtection), + ]); +} +/** + * + * @param checkCmd + * @param checkWatchCancel + * @param onLog + */ +async function _doCheck(checkCmd, checkWatchCancel, onLog) { + try { + await RootMode.execCheck(checkCmd, checkCancel, true, onLog); + logDebug(`Check command "${checkCmd}" confirmed shutdown.`); + } finally { + checkCancel = undefined; + checkWatchCancel.cancel(); + } +} + +/** + * + * @param cancellable + * @param redoRootProtection + */ +async function continueRootProtectionDuringCheck( + cancellable, + redoRootProtection +) { + try { + await RootMode.execCheck(['sleep', '30'], cancellable, false); + } catch (err) { + logDebug('RootProtection during check: Canceled'); + } + if (checkCancel === undefined) { + logDebug('RootProtection during check: Done'); + } else { + await redoRootProtection(); + logDebug('RootProtection during check: Continue'); + await continueRootProtectionDuringCheck(cancellable, redoRootProtection); + } +} + +/** + * + */ +function isChecking() { + return checkCancel !== undefined && !checkCancel.is_cancelled(); +} + +/** + * + */ +function maybeCancel() { + const doCancel = isChecking(); + if (doCancel) { + checkCancel.cancel(); + } + return doCancel; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Convenience.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Convenience.js new file mode 100644 index 0000000..1db0805 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Convenience.js @@ -0,0 +1,163 @@ +/** + * Convenience module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported MODES, WAKE_MODES, modeLabel, logDebug, proxyPromise, durationString, longDurationString, disableGuiIdle, enableGuiIdle, guiIdle, throttleTimeout */ + +const { GLib } = imports.gi; +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; +const _n = Gettext.ngettext; + +let debugMode = false; + +/** + * + * @param {...any} args + */ +function logDebug(...args) { + if (debugMode) { + log(...args); + } +} + +var MODES = ['suspend', 'poweroff', 'reboot']; +var WAKE_MODES = ['wake', 'no-wake']; +/** + * + * @param mode + */ +function modeLabel(mode) { + return { + suspend: _('Suspend'), + poweroff: _('Power Off'), + reboot: _('Restart'), + wake: _('Wake after'), + 'no-wake': _('No Wake'), + }[mode]; +} + +/** + * + * @param ProxyType + * @param session + * @param dest + * @param objectPath + */ +function proxyPromise(ProxyType, session, dest, objectPath) { + return new Promise((resolve, reject) => { + new ProxyType(session, dest, objectPath, (proxy, error) => { + if (error) { + reject(error); + } else { + resolve(proxy); + } + }); + }); +} + +/** + * + * @param seconds + */ +function durationString(seconds) { + const sign = Math.sign(seconds); + const absSec = Math.floor(Math.abs(seconds)); + const minutes = Math.floor(absSec / 60); + const hours = Math.floor(minutes / 60); + if (hours >= 3) { + return _n('%s hour', '%s hours', hours).format(sign * hours); + } else if (minutes === 0) { + return _n('%s sec', '%s secs', absSec).format( + sign * (absSec > 5 ? 10 * Math.ceil(absSec / 10) : absSec) + ); + } + return _n('%s min', '%s mins', minutes).format(sign * minutes); +} + +/** + * + * @param minutes + * @param hrFmt + * @param minFmt + */ +function longDurationString(minutes, hrFmt, minFmt) { + const hours = Math.floor(minutes / 60); + const residualMinutes = minutes % 60; + let parts = [minFmt(residualMinutes).format(residualMinutes)]; + if (hours) { + parts = [hrFmt(hours).format(hours)].concat(parts); + } + return parts.join(' '); +} + +let idleSourceId = null; +let idleCallbacks = []; +let idleEnabled = false; + +/** + * + */ +function enableGuiIdle() { + idleEnabled = true; +} + +/** + * + */ +function disableGuiIdle() { + idleEnabled = false; + idleCallbacks = []; + if (idleSourceId) { + GLib.Source.remove(idleSourceId); + } + idleSourceId = null; +} + +/** + * + * @param callback + */ +function guiIdle(callback) { + if (idleEnabled) { + idleCallbacks.push(callback); + if (!idleSourceId) { + idleSourceId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + for (const func of idleCallbacks) { + func(); + } + idleCallbacks = []; + idleSourceId = null; + return GLib.SOURCE_REMOVE; + }); + } + } +} + +/** + * + * @param timeoutFunc + * @param delayMillis + */ +function throttleTimeout(timeoutFunc, delayMillis) { + let current = null; + return [ + () => { + if (current === null) { + current = setTimeout(() => { + timeoutFunc(); + current = null; + }, delayMillis); + } + }, + () => { + if (current) { + clearTimeout(current); + current = null; + } + }, + ]; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/EndSessionDialogAware.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/EndSessionDialogAware.js new file mode 100644 index 0000000..dc0ac16 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/EndSessionDialogAware.js @@ -0,0 +1,113 @@ +/** + * EndSessionDialogAware module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported register, unregister, load, unload */ +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { Convenience } = Me.imports.lib; +const { Gio } = imports.gi; +const { loadInterfaceXML } = imports.misc.fileUtils; +const { proxyPromise, logDebug } = Convenience; + +const EndSessionDialogInf = loadInterfaceXML( + 'org.gnome.SessionManager.EndSessionDialog' +); +const EndSessionDialogProxy = + Gio.DBusProxy.makeProxyWrapper(EndSessionDialogInf); + +let endSessionDialog = null; +let onCancelAction = null; +let registered = false; + +/** + * + */ +function unregister() { + registered = false; +} +/** + * + */ +function register() { + registered = true; +} + +/** + * + * @param cancelAction + */ +function load(cancelAction) { + onCancelAction = cancelAction; + _update(); +} + +/** + * + */ +function unload() { + onCancelAction = null; + _update(); +} + +/** + * + */ +async function _update() { + try { + if (onCancelAction && !endSessionDialog) { + endSessionDialog = await proxyPromise( + EndSessionDialogProxy, + Gio.DBus.session, + 'org.gnome.Shell', + '/org/gnome/SessionManager/EndSessionDialog' + ); + } + if (endSessionDialog) { + if (onCancelAction === null) { + _disconnect(endSessionDialog); + endSessionDialog = null; + } else { + _connect(endSessionDialog, onCancelAction); + } + } + } catch (err) { + logError(err, 'EndSessionDialogProxyError'); + endSessionDialog = null; + } +} + +/** + * + * @param dialog + * @param cancelAction + */ +function _connect(dialog, cancelAction) { + if (!('_cancelSignalId' in dialog)) { + logDebug('Connect cancel of endSessionDialog...'); + dialog['_cancelSignalId'] = dialog.connectSignal('Canceled', () => { + logDebug( + `endSessionDialog cancel triggered. propagate registered: ${registered}` + ); + if (registered) { + cancelAction(); + } + }); + } +} + +/** + * + * @param dialog + */ +function _disconnect(dialog) { + const signalId = dialog['_cancelSignalId']; + if (signalId) { + logDebug('Disconnect cancel of endSessionDialog...'); + dialog.disconnectSignal(signalId); + delete dialog['_cancelSignalId']; + } +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/InfoFetcher.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/InfoFetcher.js new file mode 100644 index 0000000..84e5dce --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/InfoFetcher.js @@ -0,0 +1,120 @@ +/** + * InfoFetcher module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported InfoFetcher */ + +const { Gio, GLib } = imports.gi; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { Convenience } = Me.imports.lib; +const { logDebug, throttleTimeout } = Convenience; +const ByteArray = imports.byteArray; + +/** + * + * @param path + */ +function readFile(path) { + return new Promise((resolve, reject) => { + try { + const file = Gio.File.new_for_path(path); + file.load_contents_async(null, (f, res) => { + try { + const [, contents] = f.load_contents_finish(res); + resolve(ByteArray.toString(contents)); + GLib.free(contents); + } catch (err) { + reject(err); + } + }); + } catch (err) { + reject(err); + } + }); +} + +/** + * + */ +async function isWakeInfoLocal() { + const content = await readFile('/etc/adjtime').catch(() => ''); + return content.trim().toLowerCase().endsWith('local'); +} + +/** + * + * @param rtc + */ +async function wakeInfo(rtc) { + const content = await readFile(`/sys/class/rtc/${rtc}/wakealarm`).catch( + () => '' + ); + let timestamp = content !== '' ? parseInt(content) : -1; + if (timestamp > -1 && (await isWakeInfoLocal())) { + const dt = GLib.DateTime.new_from_unix_local(timestamp); + timestamp = dt.to_unix() - dt.get_utc_offset() / 1000000; + dt.unref(); + } + return { deadline: timestamp }; +} + +/** + * + */ +async function shutdownInfo() { + try { + const content = await readFile('/run/systemd/shutdown/scheduled'); + // content: schedule unix-timestamp (micro-seconds), warn-all, shutdown-mode + const [usec, _, mode] = content.split('\n').map(l => l.split('=')[1]); + return { + mode, + deadline: parseInt(usec) / 1000000, + }; + } catch { + return { deadline: -1 }; + } +} + +var InfoFetcher = class { + constructor(onFetch) { + this._infoTimerId = null; + this._pending = false; + this._rtc = 'rtc0'; + this._onFetch = onFetch; + [this.refresh, this._cancelRefresh] = throttleTimeout( + this._refresh.bind(this), + 300 + ); + this.refresh(); + } + + _refresh() { + logDebug('Extra info refresh...'); + this.stop(); + // restart loop + this._infoTimerId = setInterval(this.tick.bind(this), 5000); + this.tick(); + } + + stop() { + if (this._infoTimerId !== null) { + clearInterval(this._infoTimerId); + } + this._cancelRefresh(); + } + + tick() { + if (!this._pending) { + this._pending = true; + Promise.all([shutdownInfo(), wakeInfo(this._rtc)]).then( + ([schedule, wake]) => { + this._onFetch(schedule, wake); + this._pending = false; + } + ); + } + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Install.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Install.js new file mode 100644 index 0000000..860f38d --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Install.js @@ -0,0 +1,89 @@ +/** + * Install module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported installAction, checkInstalled, reset, actionLabel */ + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { Convenience, RootMode } = Me.imports.lib; +const logDebug = Convenience.logDebug; + +const { Gio } = imports.gi; +// translations +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; + +let installCancel; + +/** + * + * @param action + * @param logInstall + */ +function installAction(action, logInstall) { + if (installCancel !== undefined) { + logDebug('Trigger cancel install.'); + installCancel.cancel(); + } else { + logDebug(`Trigger ${action} action.`); + installCancel = new Gio.Cancellable(); + _installAction(action, logInstall, installCancel).finally(() => { + installCancel = undefined; + }); + } +} + +/** + * + */ +function checkInstalled() { + const scriptPath = RootMode.installedScriptPath(); + const isInstalled = scriptPath !== null; + if (isInstalled) { + logDebug(`Existing installation at: ${scriptPath}`); + } + return isInstalled; +} + +/** + * + * @param action + * @param logInstall + * @param cancel + */ +async function _installAction(action, logInstall, cancel) { + logInstall(`[${_('START')} ${actionLabel(action)}]`); + try { + if (action === 'install') { + await RootMode.installScript(cancel, logInstall); + } else { + await RootMode.uninstallScript(cancel, logInstall); + } + logInstall(`[${_('END')} ${actionLabel(action)}]`); + } catch (err) { + logInstall(`[${_('FAIL')} ${actionLabel(action)}]\n# ${err}`); + logError(err, 'InstallError'); + } +} + +/** + * + * @param action + */ +function actionLabel(action) { + return { install: _('install'), uninstall: _('uninstall') }[action]; +} + +/** + * + */ +function reset() { + if (installCancel !== undefined) { + installCancel.cancel(); + } + installCancel = undefined; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/MenuItem.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/MenuItem.js new file mode 100644 index 0000000..1085377 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/MenuItem.js @@ -0,0 +1,444 @@ +/** + * MenuItem module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported ShutdownTimer, init, uninit, MODES */ + +const { GObject, St, Gio, Clutter } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { Convenience, InfoFetcher, ScheduleInfo } = Me.imports.lib; +const { + logDebug, + modeLabel, + MODES, + WAKE_MODES, + durationString, + longDurationString, + guiIdle, +} = Convenience; + +// menu items +const PopupMenu = imports.ui.popupMenu; +const Slider = imports.ui.slider; + +// translations +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; +const _n = Gettext.ngettext; +const C_ = Gettext.pgettext; + +let ACTIONS; +let settings; + +var ShutdownTimer = GObject.registerClass( + class ShutdownTimer extends PopupMenu.PopupSubMenuMenuItem { + _init() { + super._init('', true); + // track external shutdown and wake schedule + this.infoFetcher = new InfoFetcher.InfoFetcher( + this._externalScheduleInfoTick.bind(this) + ); + + this.checkRunning = false; + this.externalScheduleInfo = new ScheduleInfo.ScheduleInfo({ + external: true, + }); + this.externalWakeInfo = new ScheduleInfo.ScheduleInfo({ + external: false, + mode: 'wake', + }); + this.internalScheduleInfo = new ScheduleInfo.ScheduleInfo({ + external: false, + deadline: settings.get_int('shutdown-timestamp-value'), + mode: settings.get_string('shutdown-mode-value'), + }); + + // submenu in status area menu with slider and toggle button + this.sliderItems = {}; + this.sliders = {}; + ['shutdown', 'wake'].forEach(prefix => { + const [item, slider] = _createSliderItem(prefix); + this.sliderItems[prefix] = item; + this.sliders[prefix] = slider; + this._onShowSliderChanged(prefix); + }); + this.switcher = new PopupMenu.PopupSwitchMenuItem('', false); + _connect(this.switcher, [['toggled', this._onToggle.bind(this)]]); + this.switcherSettingsButton = new St.Button({ + reactive: true, + can_focus: true, + track_hover: true, + accessible_name: _('Settings'), + style_class: 'system-menu-action settings-button', + }); + this.switcherSettingsButton.child = new St.Icon({ + icon_name: 'emblem-system-symbolic', + style_class: 'popup-menu-icon', + }); + _connect(this.switcherSettingsButton, [ + [ + 'clicked', + async () => { + try { + const r = ExtensionUtils.openPrefs(); + if (r) { + await r; + } + } catch { + logDebug('failed to open preferences!'); + } + }, + ], + ]); + this.switcher.add_child(this.switcherSettingsButton); + + this._onShowSettingsButtonChanged(); + this._updateSwitchLabel(); + this.icon.icon_name = 'preferences-system-time-symbolic'; + this.menu.addMenuItem(this.switcher); + // make switcher toggle without popup menu closing + this.switcher.activate = __ => { + if (this.switcher._switch.mapped) { + this.switcher.toggle(); + } + }; + this.menu.addMenuItem(this.sliderItems['shutdown']); + + this.modeItems = MODES.map(mode => { + const modeItem = new PopupMenu.PopupMenuItem(modeLabel(mode)); + _connect(modeItem, [ + [ + 'activate', + () => { + this._startMode(mode); + }, + ], + ]); + this.menu.addMenuItem(modeItem); + return [mode, modeItem]; + }); + + this.wakeItems = [ + new PopupMenu.PopupSeparatorMenuItem(), + this.sliderItems['wake'], + ...WAKE_MODES.map(mode => { + const modeItem = new PopupMenu.PopupMenuItem(modeLabel(mode)); + if (mode === 'wake') { + this.wakeModeItem = modeItem; + } + _connect(modeItem, [ + [ + 'activate', + () => ACTIONS.wakeAction(mode, _getSliderMinutes('wake')), + ], + ]); + return modeItem; + }), + ]; + this._updateWakeModeItem(); + this.wakeItems.forEach(item => { + this.menu.addMenuItem(item); + }); + this._updateShownWakeItems(); + this._updateShownModeItems(); + this._updateSelectedModeItems(); + this._onInternalShutdownTimestampChanged(); + + // handlers for changed values in settings + this.settingsHandlerIds = [ + ['shutdown-max-timer-value', this._updateSwitchLabel.bind(this)], + ['nonlinear-shutdown-slider-value', this._updateSwitchLabel.bind(this)], + ['wake-max-timer-value', this._updateWakeModeItem.bind(this)], + ['nonlinear-wake-slider-value', this._updateWakeModeItem.bind(this)], + [ + 'shutdown-slider-value', + () => { + this._updateSlider('shutdown'); + this._updateSwitchLabel(); + }, + ], + [ + 'wake-slider-value', + () => { + this._updateSlider('wake'); + this._updateWakeModeItem(); + }, + ], + ['root-mode-value', this._onRootModeChanged.bind(this)], + ['show-settings-value', this._onShowSettingsButtonChanged.bind(this)], + [ + 'show-shutdown-slider-value', + () => this._onShowSliderChanged('shutdown'), + ], + ['show-wake-slider-value', () => this._onShowSliderChanged('wake')], + ['show-wake-items-value', this._updateShownWakeItems.bind(this)], + ['show-shutdown-mode-value', this._updateShownModeItems.bind(this)], + ['shutdown-mode-value', this._onModeChange.bind(this)], + [ + 'shutdown-timestamp-value', + this._onInternalShutdownTimestampChanged.bind(this), + ], + ].map(([label, func]) => settings.connect(`changed::${label}`, func)); + } + + _onRootModeChanged() { + Promise.all([ + ACTIONS.maybeStopRootModeProtection(this.internalScheduleInfo), + ACTIONS.maybeStartRootModeProtection(this.internalScheduleInfo), + ]).then(() => { + this._updateSwitchLabel(); + }); + } + + _onModeChange() { + // redo Root-mode protection + ACTIONS.maybeStopRootModeProtection(this.internalScheduleInfo, true) + .then(() => { + this._updateCurrentMode(); + logDebug(`Shutdown mode: ${this.internalScheduleInfo.mode}`); + guiIdle(this._updateSelectedModeItems.bind(this)); + }) + .then(() => + ACTIONS.maybeStartRootModeProtection(this.internalScheduleInfo) + ); + } + + _updateCurrentMode() { + this.internalScheduleInfo = this.internalScheduleInfo.copy({ + mode: settings.get_string('shutdown-mode-value'), + }); + + ACTIONS.onShutdownScheduleChange(this.internalScheduleInfo); + this.updateShutdownInfo(); + } + + _onInternalShutdownTimestampChanged() { + this.internalScheduleInfo = this.internalScheduleInfo.copy({ + deadline: settings.get_int('shutdown-timestamp-value'), + }); + + ACTIONS.onShutdownScheduleChange(this.internalScheduleInfo); + this.switcher.setToggleState(this.internalScheduleInfo.scheduled); + this.updateShutdownInfo(); + } + + /* Schedule Info updates */ + _externalScheduleInfoTick(info, wakeInfo) { + this.externalScheduleInfo = this.externalScheduleInfo.copy({ + ...info, + }); + this.externalWakeInfo = this.externalWakeInfo.copy({ ...wakeInfo }); + guiIdle(this.updateShutdownInfo.bind(this)); + } + + _updateShownModeItems() { + const activeModes = settings + .get_string('show-shutdown-mode-value') + .split(',') + .map(s => s.trim().toLowerCase()) + .filter(s => MODES.includes(s)); + this.modeItems.forEach(([mode, item]) => { + const position = activeModes.indexOf(mode); + if (position > -1) { + this.menu.moveMenuItem(item, position + 2); + } + item.visible = position > -1; + }); + } + + updateShutdownInfo() { + let shutdownLabel; + if (this.internalScheduleInfo.scheduled && this.checkRunning) { + const secPassed = Math.max(0, -this.internalScheduleInfo.secondsLeft); + shutdownLabel = _('Check %s for %s').format( + this.internalScheduleInfo.modeText, + durationString(secPassed) + ); + } else { + const info = this.externalScheduleInfo.isMoreUrgendThan( + this.internalScheduleInfo + ) + ? this.externalScheduleInfo + : this.internalScheduleInfo; + shutdownLabel = info.label; + } + this.label.text = + [shutdownLabel, this.externalWakeInfo.label] + .filter(v => !!v) + .join('\n') || _('Shutdown Timer'); + } + + _updateSelectedModeItems() { + this.modeItems.forEach(([mode, item]) => { + item.setOrnament( + mode === this.internalScheduleInfo.mode + ? PopupMenu.Ornament.DOT + : PopupMenu.Ornament.NONE + ); + }); + } + + // update timer value if slider has changed + _updateSlider(prefix) { + this.sliders[prefix].value = + settings.get_double(`${prefix}-slider-value`) / 100.0; + } + + _updateSwitchLabel() { + const minutes = Math.abs(_getSliderMinutes('shutdown')); + const timeStr = longDurationString( + minutes, + h => _n('%s hr', '%s hrs', h), + m => _n('%s min', '%s mins', m) + ); + this.switcher.label.text = settings.get_boolean('root-mode-value') + ? _('%s (protect)').format(timeStr) + : timeStr; + } + + _updateWakeModeItem() { + const minutes = Math.abs(_getSliderMinutes('wake')); + this.wakeModeItem.label.text = C_('WakeButtonText', '%s %s').format( + modeLabel('wake'), + longDurationString( + minutes, + h => _n('%s hour', '%s hours', h), + m => _n('%s minute', '%s minutes', m) + ) + ); + } + + _onShowSettingsButtonChanged() { + this.switcherSettingsButton.visible = settings.get_boolean( + 'show-settings-value' + ); + } + + _updateShownWakeItems() { + this.wakeItems.forEach(item => { + item.visible = settings.get_boolean('show-wake-items-value'); + }); + this._onShowSliderChanged('wake'); + } + + _onShowSliderChanged(settingsPrefix) { + this.sliderItems[settingsPrefix].visible = + (settingsPrefix !== 'wake' || + settings.get_boolean('show-wake-items-value')) && + settings.get_boolean(`show-${settingsPrefix}-slider-value`); + } + + _startMode(mode) { + settings.set_string('shutdown-mode-value', mode); + ACTIONS.startSchedule( + _getSliderMinutes('shutdown'), + _getSliderMinutes('wake') + ); + } + + // toggle button starts/stops shutdown timer + _onToggle() { + if (this.switcher.state) { + // start shutdown timer + ACTIONS.startSchedule( + _getSliderMinutes('shutdown'), + _getSliderMinutes('wake') + ); + } else { + // stop shutdown timer + ACTIONS.stopSchedule(); + } + } + + destroy() { + this.infoFetcher.stop(); + this.settingsHandlerIds.forEach(handlerId => { + settings.disconnect(handlerId); + }); + this.settingsHandlerIds = []; + super.destroy(); + } + } +); + +/** + * + * @param settingsObj + * @param actions + */ +function init(settingsObj, actions) { + settings = settingsObj; + ACTIONS = actions; +} + +/** + * + */ +function uninit() { + settings = null; + ACTIONS = null; +} + +/** + * + * @param prefix + */ +function _getSliderMinutes(prefix) { + let sliderValue = settings.get_double(`${prefix}-slider-value`) / 100.0; + const rampUp = settings.get_double(`nonlinear-${prefix}-slider-value`); + const ramp = x => Math.expm1(rampUp * x) / Math.expm1(rampUp); + return Math.floor( + (rampUp === 0 ? sliderValue : ramp(sliderValue)) * + settings.get_int(`${prefix}-max-timer-value`) + ); +} + +/** + * + * @param item + * @param connections + */ +function _connect(item, connections) { + const handlerIds = connections.map(([label, func]) => + item.connect(label, func) + ); + const destroyId = item.connect('destroy', () => { + handlerIds.concat(destroyId).forEach(handlerId => { + item.disconnect(handlerId); + }); + }); +} + +/** + * + * @param settingsPrefix + */ +function _createSliderItem(settingsPrefix) { + const sliderValue = + settings.get_double(`${settingsPrefix}-slider-value`) / 100.0; + const item = new PopupMenu.PopupBaseMenuItem({ activate: false }); + const sliderIcon = new St.Icon({ + icon_name: + settingsPrefix === 'wake' ? 'alarm-symbolic' : 'system-shutdown-symbolic', + style_class: 'popup-menu-icon', + }); + item.add(sliderIcon); + const slider = new Slider.Slider(sliderValue); + _connect(slider, [ + [ + 'notify::value', + () => { + settings.set_double( + `${settingsPrefix}-slider-value`, + slider.value * 100 + ); + }, + ], + ]); + item.add_child(slider); + return [item, slider]; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/RootMode.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/RootMode.js new file mode 100644 index 0000000..bed5e15 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/RootMode.js @@ -0,0 +1,279 @@ +/** + * RootMode module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported shutdown, shutdownCancel, wake, wakeCancel, installScript, uninstallScript */ +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const logDebug = Me.imports.lib.Convenience.logDebug; + +const { Gio, GLib } = imports.gi; + +// translations +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; + +/** + * + * @param stream + * @param cancellable + */ +function readLine(stream, cancellable) { + return new Promise((resolve, reject) => { + stream.read_line_async(0, cancellable, (s, res) => { + try { + const line = s.read_line_finish_utf8(res)[0]; + + if (line !== null) { + resolve(line); + } else { + reject(new Error('No line was read!')); + } + } catch (e) { + reject(e); + } + }); + }); +} + +/** + * + * @param str + */ +function quoteEscape(str) { + return str.replaceAll('\\', '\\\\').replaceAll('"', '\\"'); +} + +/** + * Execute a command asynchronously and check the exit status. + * + * If given, @cancellable can be used to stop the process before it finishes. + * + * @param {string[] | string} argv - a list of string arguments or command line that will be parsed + * @param {Gio.Cancellable} [cancellable] - optional cancellable object + * @param {boolean} shell - run command as shell command + * @param logFunc + * @returns {Promise} - The process success + */ +function execCheck( + argv, + cancellable = null, + shell = true, + logFunc = undefined +) { + if (!shell && typeof argv === 'string') { + argv = GLib.shell_parse_argv(argv)[1]; + } + + const isRootProc = argv[0] && argv[0].endsWith('pkexec'); + + if (shell && Array.isArray(argv)) { + argv = argv.map(c => `"${quoteEscape(c)}"`).join(' '); + } + let cancelId = 0; + let proc = new Gio.Subprocess({ + argv: (shell ? ['/bin/sh', '-c'] : []).concat(argv), + flags: + logFunc !== undefined + ? Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE + : Gio.SubprocessFlags.NONE, + }); + proc.init(cancellable); + + if (cancellable instanceof Gio.Cancellable) { + cancelId = cancellable.connect(() => { + if (logFunc !== undefined) { + if (isRootProc) { + logFunc(`# ${_('Can not cancel root process!')}`); + } else { + logFunc(`[${_('CANCEL')}]`); + } + } + proc.force_exit(); + }); + } + let stdoutStream = null; + let stderrStream = null; + let stdCancel = null; + + if (logFunc !== undefined) { + stdoutStream = new Gio.DataInputStream({ + base_stream: proc.get_stdout_pipe(), + close_base_stream: true, + }); + + stderrStream = new Gio.DataInputStream({ + base_stream: proc.get_stderr_pipe(), + close_base_stream: true, + }); + const readNextLine = async (stream, prefix) => { + stdCancel = new Gio.Cancellable(); + const line = await readLine(stream, stdCancel); + logFunc(prefix + line); + logDebug(line); + return readNextLine(stream, prefix); + }; + // read stdout and stderr asynchronously + readNextLine(stdoutStream, '').catch(() => {}); + readNextLine(stderrStream, '# ').catch(() => {}); + } + + return new Promise((resolve, reject) => { + proc.wait_check_async(null, (p, res) => { + try { + const success = p.wait_check_finish(res); + if (stdCancel !== null) { + stdCancel.cancel(); + } + if (!success) { + let status = p.get_exit_status(); + + throw new Gio.IOErrorEnum({ + code: Gio.io_error_from_errno(status), + message: GLib.strerror(status), + }); + } + + resolve(); + } catch (e) { + reject(e); + } finally { + const maybeCloseStream = stream => { + if (stream !== null && !stream.is_closed()) { + stream.close_async(0, null, (s, sRes) => { + try { + s.close_finish(sRes); + } catch (e) { + logError(e, 'StreamCloseError'); + } + }); + } + }; + maybeCloseStream(stdoutStream); + maybeCloseStream(stderrStream); + if (cancelId > 0) { + cancellable.disconnect(cancelId); + } + } + }); + }); +} + +/** + * + */ +function installedScriptPath() { + for (const name of [ + 'shutdowntimerctl', + `shutdowntimerctl-${GLib.get_user_name()}`, + ]) { + const standard = GLib.find_program_in_path(name); + if (standard !== null) { + return standard; + } + for (const bindir of ['/usr/local/bin/', '/usr/bin/']) { + const path = bindir + name; + logDebug(`Looking for: ${path}`); + if (Gio.File.new_for_path(path).query_exists(null)) { + return path; + } + } + } + return null; +} + +/** + * + * @param action + * @param cancellable + * @param logFunc + */ +function _runInstaller(action, cancellable, logFunc) { + const user = GLib.get_user_name(); + logDebug(`? installer.sh --tool-user ${user} ${action}`); + return execCheck( + [ + 'pkexec', + Me.dir.get_child('tool').get_child('installer.sh').get_path(), + '--tool-user', + user, + action, + ], + cancellable, + false, + logFunc + ); +} + +/** + * + * @param cancellable + * @param logFunc + */ +async function installScript(cancellable, logFunc) { + // install for user if installed in the /home directory + await _runInstaller('install', cancellable, logFunc); + return true; +} + +/** + * + * @param cancellable + * @param logFunc + */ +async function uninstallScript(cancellable, logFunc) { + await _runInstaller('uninstall', cancellable, logFunc); + return true; +} + +/** + * + * @param args + * @param noScriptArgs + */ +function runWithScript(args, noScriptArgs) { + const installedScript = installedScriptPath(); + if (installedScript !== null) { + return execCheck(['pkexec', installedScript].concat(args), null, false); + } + if (noScriptArgs === undefined) { + throw new Error(_('Privileged script installation required!')); + } + return execCheck(noScriptArgs, null, false); +} + +/** + * + * @param minutes + * @param reboot + */ +function shutdown(minutes, reboot = false) { + return runWithScript( + [reboot ? 'reboot' : 'shutdown', `${minutes}`], + ['shutdown', reboot ? '-r' : '-P', `${minutes}`] + ); +} + +/** + * + */ +function shutdownCancel() { + return runWithScript(['shutdown-cancel'], ['shutdown', '-c']); +} + +/** + * + * @param minutes + */ +function wake(minutes) { + return runWithScript(['wake', `${minutes}`]); +} + +/** + * + */ +function wakeCancel() { + return runWithScript(['wake-cancel']); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/ScheduleInfo.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/ScheduleInfo.js new file mode 100644 index 0000000..9fd4d80 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/ScheduleInfo.js @@ -0,0 +1,84 @@ +/** + * ScheduleInfo module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported ScheduleInfo */ +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { durationString } = Me.imports.lib.Convenience; + +const { GLib } = imports.gi; + +// translations +const Gettext = imports.gettext.domain('ShutdownTimer'); +const _ = Gettext.gettext; + +var ScheduleInfo = class { + constructor({ mode = '?', deadline = -1, external = false }) { + this._v = { mode, deadline, external }; + } + + copy(vals) { + return new ScheduleInfo({ ...this._v, ...vals }); + } + + get deadline() { + return this._v.deadline; + } + + get external() { + return this._v.external; + } + + get mode() { + return this._v.mode; + } + + get scheduled() { + return this.deadline > -1; + } + + get secondsLeft() { + return this.deadline - GLib.DateTime.new_now_utc().to_unix(); + } + + get minutes() { + return Math.floor(this.secondsLeft / 60); + } + + get modeText() { + const texts = { + suspend: _('suspend'), + poweroff: _('shutdown'), + reboot: _('reboot'), + wake: _('wakeup'), + }; + return this.mode in texts ? texts[this.mode] : texts['poweroff']; + } + + get label() { + let label = ''; + if (this.scheduled) { + label = _('%s until %s').format( + durationString(this.secondsLeft), + this.modeText + ); + if (this.external) { + label = _('%s (sys)').format(label); + } + } + return label; + } + + isMoreUrgendThan(otherInfo) { + return ( + !otherInfo.scheduled || + (this.scheduled && + // external deadline is instant, internal deadline has 1 min slack time + (this.external ? this.deadline : this.deadline + 58) < + otherInfo.deadline) + ); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/SessionModeAware.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/SessionModeAware.js new file mode 100644 index 0000000..105e031 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/SessionModeAware.js @@ -0,0 +1,33 @@ +/** + * ScreenModeAware module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported load, unload */ +const Main = imports.ui.main; + +let sessionId = null; + +/** + * + * @param onSessionModeChange + */ +function load(onSessionModeChange) { + if (sessionId === null) { + sessionId = Main.sessionMode.connect('updated', session => + onSessionModeChange(session.currentMode) + ); + } +} + +/** + * + */ +function unload() { + if (sessionId !== null) { + Main.sessionMode.disconnect(sessionId); + sessionId = null; + } +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Textbox.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Textbox.js new file mode 100644 index 0000000..6f395e1 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Textbox.js @@ -0,0 +1,119 @@ +/** + * Textbox module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported showTextbox, hideAll, init, uninit */ +const Main = imports.ui.main; +const { St, Clutter } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const { Convenience } = Me.imports.lib; +const { logDebug, throttleTimeout } = Convenience; +let textboxes = []; + +let throttleUpdate = null; +let throttleUpdateCancel = null; + +/** + * + */ +function init() { + [throttleUpdate, throttleUpdateCancel] = throttleTimeout(_update, 50); +} + +/** + * + */ +function uninit() { + throttleUpdate = null; + throttleUpdateCancel = null; +} + +// show textbox with message +/** + * + * @param textmsg + */ +function showTextbox(textmsg) { + for (const t of textboxes) { + // replace old textbox if it has the same text + if (t.text === textmsg) { + t['_hidden'] = 1; + } + } + logDebug(`show textbox: ${textmsg}`); + const textbox = new St.Label({ + style_class: 'textbox-label', + text: textmsg, + opacity: 0, + }); + Main.uiGroup.add_actor(textbox); + textboxes.unshift(textbox); + throttleUpdate(); +} + +/** + * + */ +function _update() { + // remove hidden textboxes + textboxes = textboxes.filter(t => { + if (t['_hidden']) { + const sid = t['_sourceId']; + if (sid) { + clearTimeout(sid); + } + delete t['_sourceId']; + t.destroy(); + } + return !t['_hidden']; + }); + const monitor = Main.layoutManager.primaryMonitor; + let heightOffset = 0; + textboxes.forEach((textbox, i) => { + if (i === 0) { + heightOffset = -textbox.height / 2; + } + textbox.set_position( + monitor.x + Math.floor(monitor.width / 2 - textbox.width / 2), + monitor.y + Math.floor(monitor.height / 2 + heightOffset) + ); + heightOffset += textbox.height + 10; + if (!('_sourceId' in textbox)) { + // start fadeout of textbox after 3 seconds + textbox['_sourceId'] = setTimeout(() => { + textbox['_sourceId'] = 0; + textbox.ease({ + opacity: 0, + duration: 1000, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => { + textbox['_hidden'] = 1; + throttleUpdate(); + }, + }); + }, 3000); + } + if (textbox['_sourceId']) { + // set opacity before fadeout starts + textbox.opacity = + i === 0 + ? 255 + : Math.max(25, 25 + 230 * (1 - heightOffset / (monitor.height / 2))); + } + }); +} + +/** + * + */ +function hideAll() { + throttleUpdateCancel(); + for (const t of textboxes) { + t['_hidden'] = 1; + } + _update(); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Timer.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Timer.js new file mode 100644 index 0000000..0c2a38f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/lib/Timer.js @@ -0,0 +1,118 @@ +/** + * Timer module + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported Timer */ +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { RootMode, ScheduleInfo } = Me.imports.lib; +const logDebug = Me.imports.lib.Convenience.logDebug; + +const { Gio } = imports.gi; + +/* TIMER */ +var Timer = class { + constructor(callbackAction, initialMode = 'shutdown') { + this._timerMaxSeconds = 0; + this._timerCancel = null; + this._callbackAction = callbackAction; + this._tick = null; + this._timerId = null; + this.info = new ScheduleInfo.ScheduleInfo({ mode: initialMode }); + } + + setTickCallback(tick) { + this._tick = tick; + } + + adjustTo(info) { + const newDeadline = info.deadline !== this.info.deadline; + this.info = info; + if (info.scheduled) { + if (newDeadline) { + // update proc process for new deadline + this.startProcTimer(); + } + this.startForegroundTick(); + logDebug( + `Started timer: ${this.info.minutes}min remaining (deadline: ${this.info.deadline})` + ); + } else { + this.stopTimer(); + logDebug( + `Stopped timer: ${this.info.minutes}min remaining (deadline: ${this.info.deadline})` + ); + } + } + + stopTimer() { + this.stopProcTimer(); + this.stopForeground(); + } + + _maybeRunTimerAction() { + if (this._timerCancel !== null) { + // ensure timer action is only run once + logDebug(`Running '${this.info.mode}' timer action...`); + this._callbackAction(this.info.mode); + } + } + + async startProcTimer() { + // secondary timer witch calls a sleep process as timer + this.stopProcTimer(); + + const secs = this.info.secondsLeft; + this._timerCancel = new Gio.Cancellable(); + try { + if (secs > 0) { + await RootMode.execCheck( + ['sleep', `${secs}`], + this._timerCancel, + false + ); + } + this._maybeRunTimerAction(); + } catch { + } finally { + this._timerCancel = null; + } + } + + stopProcTimer() { + if (this._timerCancel !== null) { + this._timerCancel.cancel(); + } + this._timerCancel = null; + } + + _maybeTick() { + if (this._tick !== null) { + this._tick(); + } + } + + startForegroundTick() { + if (this._timerId === null) { + // primary timer which updates ticks every second + this._timerId = setInterval(() => { + this._maybeTick(); + if (!this.info.scheduled || this.info.secondsLeft < 0) { + // timer completed + this._maybeRunTimerAction(); + this.stopTimer(); + } + }, 1000); + this._maybeTick(); + } + } + + stopForeground() { + if (this._timerId) { + clearInterval(this._timerId); + } + this._timerId = null; + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/cs/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/cs/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..65eec92 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/cs/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/de/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/de/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..5b231b2 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/de/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/el/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/el/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..307e9dc Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/el/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/es/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/es/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..22c1d73 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/es/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/fr/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/fr/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..f1b1d61 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/fr/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/it/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/it/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..ad37b93 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/it/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/nl/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/nl/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..da584ab Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/nl/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pl/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pl/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..1f2c4ec Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pl/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pt/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pt/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..0e87a33 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/pt/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/ru/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/ru/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..c3199ec Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/ru/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/zh_CN/LC_MESSAGES/ShutdownTimer.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/zh_CN/LC_MESSAGES/ShutdownTimer.mo new file mode 100644 index 0000000..0092074 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/locale/zh_CN/LC_MESSAGES/ShutdownTimer.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/metadata.json new file mode 100644 index 0000000..0cc06c7 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/metadata.json @@ -0,0 +1,17 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Shutdown/reboot/suspend the device after a specific time or wake with a rtc alarm.\n\nThe screen-saver will not interrupt the timer. A privileged control script may be installed to control shutdown and rtcwake as user. Additionally, a check command may be configured before shutdown.", + "gettext-domain": "ShutdownTimer", + "name": "Shutdown Timer", + "session-modes": [ + "user", + "unlock-dialog" + ], + "settings-schema": "org.gnome.shell.extensions.shutdowntimer-deminder", + "shell-version": [ + "42" + ], + "url": "https://github.com/Deminder/ShutdownTimer", + "uuid": "ShutdownTimer@deminder", + "version": 31 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules new file mode 100644 index 0000000..05ec286 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules @@ -0,0 +1,8 @@ +polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.policykit.exec" && + action.lookup("program") == "{{TOOL_OUT}}" && + subject.isInGroup("{{TOOL_USER}}")) + { + return polkit.Result.YES; + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules.legacy b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules.legacy new file mode 100644 index 0000000..7f00aa8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/10-dem.shutdowntimer.settimers.rules.legacy @@ -0,0 +1,12 @@ +polkit.addRule(function (action, subject) { + var idx = action.id.lastIndexOf("."); + var username_stripped = action.id.substring(0, idx); + var username = action.id.substring(idx + 1); + if (username_stripped === "{{RULE_BASE}}") { + if (subject.user === username) { + return polkit.Result.YES; + } else { + return polkit.Result.NO; + } + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/dem.shutdowntimer.policy.in b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/dem.shutdowntimer.policy.in new file mode 100644 index 0000000..6f93f7b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/polkit/dem.shutdowntimer.policy.in @@ -0,0 +1,20 @@ + + + + Shutdown Timer + https://github.com/Deminder/ShutdownTimer + + + Control shutdown and rtc wake alarm schedule + Steuerung des Ausschalt-Planers und des RTC-Weck-Alarms + No Authorization required to control shutdown or rtc wake alarm. + Keine Autorisierung zur Steuerung des Ausschalt-Planers oder RTC-Weck-Alarms notwendig. + + yes + yes + yes + + {{PATH}} + 3.0.0 + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/prefs.js new file mode 100644 index 0000000..e5d8119 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/prefs.js @@ -0,0 +1,229 @@ +/** + * Extension preferences GUI + * + * @author Deminder + * @copyright 2021 + * @license GNU General Public License v3.0 + */ +/* exported init, fillPreferencesWindow */ +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +const { Install, Convenience } = Me.imports.lib; +const { logDebug } = Convenience; +const { enableGuiIdle, disableGuiIdle, guiIdle, modeLabel, MODES } = + Convenience; + +const { GLib, Gtk, Gio } = imports.gi; + +/** + * + */ +function init() { + ExtensionUtils.initTranslations(); +} + +const templateComponents = { + shutdown: { + 'shutdown-mode': 'combo', + 'root-mode': 'switch', + 'show-end-session-dialog': 'switch', + 'shutdown-max-timer': 'adjustment', + 'shutdown-slider': 'adjustment', + 'nonlinear-shutdown-slider': 'adjustment', + }, + wake: { + 'auto-wake': 'switch', + 'wake-max-timer': 'adjustment', + 'wake-slider': 'adjustment', + 'nonlinear-wake-slider': 'adjustment', + }, + display: { + 'show-settings': 'switch', + 'show-shutdown-mode': 'buffer', + 'show-shutdown-slider': 'switch', + 'show-textboxes': 'switch', + 'show-wake-slider': 'switch', + 'show-wake-items': 'switch', + }, + check: { + 'check-command': 'textbuffer', + 'enable-check-command': 'switch', + }, +}; + +/** + * + * @param pageId + * @param builder + * @param settings + * @param handlers + */ +function initPage(pageId, builder, settings, handlers) { + const page = builder.get_object(pageId); + const pageName = pageId.split('_').at(-1); + if (!page) { + throw new Error(`${pageId} not found!`); + } + + const connectComp = (baseName, component) => { + const baseId = baseName.replaceAll('-', '_'); + const settingsName = `${baseName}-value`; + const compId = `${baseId}_${component}`; + const comp = builder.get_object(compId); + if (!comp) { + throw new Error(`Component not found in template: ${compId}`); + } + if (compId === 'shutdown_mode_combo') { + // replace combo box entries + comp.remove_all(); + MODES.forEach(mode => { + comp.append(mode, modeLabel(mode)); + }); + } + + settings.bind( + settingsName, + comp, + { + adjustment: 'value', + switch: 'active', + textbuffer: 'text', + buffer: 'text', + combo: 'active-id', + }[component], + Gio.SettingsBindFlags.DEFAULT + ); + + if (compId === 'show_shutdown_mode_buffer') { + builder + .get_object(`${baseId}_entry`) + .set_placeholder_text( + `${MODES.join(',')} (${MODES.map(modeLabel).join(', ')})` + ); + } + }; + + if (pageName in templateComponents) { + for (const [k, v] of Object.entries(templateComponents[pageName])) { + connectComp(k, v); + } + } + + const lineIter = (buffer, lineIndex) => { + const [ok, iter] = buffer.get_iter_at_line(lineIndex); + if (!ok) { + throw new Error(`Line ${lineIndex} not found!`); + } + return iter; + }; + + if (pageName === 'check') { + // check command textbuffer + const checkCommandBuffer = builder.get_object('check_command_textbuffer'); + const commentTag = new Gtk.TextTag({ foreground: 'grey' }); + checkCommandBuffer.get_tag_table().add(commentTag); + const applyCommentTags = b => { + b.remove_tag(commentTag, b.get_start_iter(), b.get_end_iter()); + const lc = b.get_line_count(); + for (let i = 0; i < lc; i++) { + const startIter = lineIter(b, i); + const endIter = lc === i + 1 ? b.get_end_iter() : lineIter(b, i + 1); + const line = b.get_text(startIter, endIter, false); + if (line.trimLeft().startsWith('#')) { + b.apply_tag(commentTag, startIter, endIter); + } + } + }; + applyCommentTags(checkCommandBuffer); + handlers.push([ + checkCommandBuffer, + checkCommandBuffer.connect('changed', applyCommentTags), + ]); + } else if (pageName === 'install') { + // install log textbuffer updates + const logTextBuffer = builder.get_object('install_log_textbuffer'); + const scrollAdj = builder.get_object('installer_scrollbar_adjustment'); + const errorTag = new Gtk.TextTag({ foreground: 'red' }); + const successTag = new Gtk.TextTag({ foreground: 'green' }); + logTextBuffer.get_tag_table().add(errorTag); + logTextBuffer.get_tag_table().add(successTag); + const appendLogLine = line => { + line = ['[', '#'].includes(line[0]) ? line : ` ${line}`; + logTextBuffer.insert(logTextBuffer.get_end_iter(), `${line}\n`, -1); + const lastLineIndex = logTextBuffer.get_line_count() - 1; + const applyTag = tag => { + logTextBuffer.apply_tag( + tag, + lineIter(logTextBuffer, lastLineIndex - 1), + lineIter(logTextBuffer, lastLineIndex) + ); + }; + if (line.startsWith('# ')) { + applyTag(errorTag); + } else if (line.endsWith('🟢')) { + applyTag(successTag); + } + guiIdle(() => scrollAdj.set_value(1000000)); + }; + + const installSwitch = builder.get_object('install_policy_switch'); + installSwitch.set_active(Install.checkInstalled()); + const switchHandlerId = installSwitch.connect('notify::active', () => + Install.installAction( + installSwitch.get_active() ? 'install' : 'uninstall', + message => guiIdle(() => message.split('\n').forEach(appendLogLine)) + ) + ); + handlers.push([installSwitch, switchHandlerId]); + + // clear log + guiIdle(() => logTextBuffer.set_text('', -1)); + } + return page; +} + +/** + * + * @param window + */ +function fillPreferencesWindow(window) { + const builder = Gtk.Builder.new(); + builder.add_from_file( + Me.dir.get_child('ui').get_child('prefs.ui').get_path() + ); + + const settings = ExtensionUtils.getSettings(); + const handlers = []; + const pageNames = ['install', 'shutdown', 'wake', 'display', 'check'].map( + n => `shutdowntimer-prefs-${n}` + ); + enableGuiIdle(); + for (const page of pageNames.map(name => + initPage(name.replaceAll('-', '_'), builder, settings, handlers) + )) { + window.add(page); + } + const selPageName = + pageNames[settings.get_int('preferences-selected-page-value')]; + if (selPageName) { + window.set_visible_page_name(selPageName); + } + const pageVisHandlerId = window.connect('notify::visible-page-name', () => { + logDebug(window.get_visible_page_name()); + settings.set_int( + 'preferences-selected-page-value', + pageNames.indexOf(window.get_visible_page_name()) + ); + }); + handlers.push([window, pageVisHandlerId]); + // release all resources on destroy + const destroyId = window.connect('destroy', () => { + disableGuiIdle(); + handlers.forEach(([comp, handlerId]) => { + comp.disconnect(handlerId); + }); + Install.reset(); + window.disconnect(destroyId); + }); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/gschemas.compiled new file mode 100644 index 0000000..9af400a Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/org.gnome.shell.extensions.shutdowntimer-deminder.gschema.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/org.gnome.shell.extensions.shutdowntimer-deminder.gschema.xml new file mode 100644 index 0000000..c55da2a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/schemas/org.gnome.shell.extensions.shutdowntimer-deminder.gschema.xml @@ -0,0 +1,135 @@ + + + + + + 180 + Maximum shutdown time (in minutes) + Set maximum selectable shutdown time of the slider (in minutes). Use only values greater zero. + + + + 1440 + Maximum wake time (in minutes) + Set maximum selectable wake time of the slider (in minutes). Use only values greater zero. + + + + false + Automatically start and stop wake on shutdown timer toggle + Enable/Disable the wake alarm when the shutdown timer is started/stopped. + + + + -1 + Scheduled shutdown timestamp. + Unix time in seconds of scheduled shutdown or -1 if disabled. + + + + 70 + Wake slider position (in percent) + Set wake slider position as percent of the maximum time. Must be in range 0 and 100. + + + + 1.5 + Ramp-up of non-linear wake slider value + Exponential ramp-up for wake time slider + + + + 70 + Shutdown slider position (in percent) + Set shutdown slider position as percent of the maximum time. Must be in range 0 and 100. + + + + 0 + Ramp-up of non-linear shutdown slider value + Exponential ramp-up for shutdown time slider + + + + true + Show settings button + Show/hide settings button in widget. + + + + true + Show shutdown slider + Show/hide shutdown slider in widget. + + + + true + Show wake slider + Show/hide wake slider in widget. + + + + false + Show all wake items + Show/hide all wake items in widget. + + + + true + Show notification text boxes + Show/hide notification text boxes on screen. + + + + false + Root mode + Set root mode on/off. In root mode powering off is done via 'pkexec' and 'shutdown' terminal command. + + + + true + Show end-session dialog + Show the end-session dialog for reboot and shutdown if screensaver is inactive. + + + + "poweroff,suspend" + Shown shutdown modes + Comma-separated shutdown modes which are shown in the popup menu + + + + "poweroff" + Use mode + Mode to use for timer action + + + + "# Examples ... + +# Run a pre-shutdown script (e.g. updates or backups) +# ~/.local/scripts/pre-shutdown.sh + +# Wait for a process to exit +# tail -f --pid=$PID + +# Activate the screen saver +# xdg-screensaver activate" + Check command(s) + Run command(s) before shutdown command. Proceed with shutdown only if check command succeeds. + + + + true + Enable check command + Check command is skipped if disabled. + + + + 0 + Last selected page in the preferences. + Last selected page in the preferences. + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/stylesheet.css new file mode 100644 index 0000000..092263c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/stylesheet.css @@ -0,0 +1,28 @@ +/** + AUTHOR: Daniel Neumann +**/ + +.textbox-label { + font-size: 2em; + font-weight: bold; + color: #ffffff; + background-color: rgba(10, 10, 10, 0.7); + border-radius: 0.5em; + padding: 0.5em; +} + +.settings-button { + padding: 4px; + border-radius: 32px; + margin: 1px; +} + +.settings-button:hover, +.settings-button:focus { + padding: 5px; + margin: 0px; +} + +.settings-button > StIcon { + icon-size: 15px; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/installer.sh b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/installer.sh new file mode 100644 index 0000000..0b2fa8a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/installer.sh @@ -0,0 +1,261 @@ +#!/bin/bash + +# installer.sh - This script installs a policykit rule for the Shutdown Timer gnome-shell extension. +# +# This file is part of the gnome-shell extension ShutdownTimer@Deminder. + +# Authors: Martin Koppehel , Fin Christensen (cpupower extension), Deminder + +set -e + +################################ +# EXTENSION SPECIFIC OPTIONS: # +################################ + +EXTENSION_NAME="Shutdown Timer" +ACTION_BASE="dem.shutdowntimer" +RULE_BASE="$ACTION_BASE.settimers" +CFC_BASE="shutdowntimerctl" +POLKIT_DIR="polkit" +VERSION=1 + + +EXIT_SUCCESS=0 +EXIT_INVALID_ARG=1 +EXIT_FAILED=2 +EXIT_NEEDS_UPDATE=3 +EXIT_NEEDS_SECURITY_UPDATE=4 +EXIT_NOT_INSTALLED=5 +EXIT_MUST_BE_ROOT=6 + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #stackoverflow 59895 + +export TEXTDOMAINDIR="$DIR/../locale" +export TEXTDOMAIN="ShutdownTimer" +function gtxt() { + gettext "$1" +} + +function recent_polkit() { + printf -v versions '%s\n%s' "$(pkaction --version | cut -d' ' -f3)" "0.106" + if [[ $versions != "$(sort -V <<< "$versions")" ]];then + echo "available" + else + echo "unavailable" + fi +} + +function check_support() { + RECENT_STR=", stand-alone polkit rules $(recent_polkit)" + if which rtcwake >/dev/null 2>&1 + then + echo "rtcwake supported${RECENT_STR}" + exit ${EXIT_SUCCESS} + else + echo "rtcwake unsupported${RECENT_STR}" + exit ${EXIT_FAILED} + fi +} + +function fail() { + echo "$(gtxt "Failed")${1}" >&2 && exit ${EXIT_FAILED} +} +DEFAULT_SUCCESS_MSG=$(gtxt 'Success') + +function success() { + echo -n "${1:-$DEFAULT_SUCCESS_MSG}" + echo -e "\U1F7E2" +} + + + +######################## +# GENERALIZED SCRIPT: # +######################## + +function usage() { + echo "Usage: installer.sh [options] {supported,install,check,update,uninstall}" + echo + echo "Available options:" + echo " --tool-user USER Set the user of the tool (default: \$USER)" + echo + exit ${EXIT_INVALID_ARG} +} + +if [ $# -lt 1 ] +then + usage +fi + +ACTION="" +TOOL_USER="$USER" +while [[ $# -gt 0 ]] +do + key="$1" + + # we have to use command line arguments here as pkexec does not support + # setting environment variables + case $key in + --tool-user) + TOOL_USER="$2" + shift + shift + ;; + supported|install|check|update|uninstall) + if [ -z "$ACTION" ] + then + ACTION="$1" + else + echo "Too many actions specified. Please give at most 1." + usage + fi + shift + ;; + *) + echo "Unknown argument $key" + usage + ;; + esac +done + + +CFC_DIR="/usr/local/bin" +RULE_DIR="/etc/polkit-1/rules.d" + +RULE_IN="${DIR}/../${POLKIT_DIR}/10-$RULE_BASE.rules" +if [[ "$(recent_polkit)" != "available" ]];then + RULE_IN="${RULE_IN}.legacy" + ACTION_IN="${DIR}/../${POLKIT_DIR}/${ACTION_BASE}.policy.in" +fi +TOOL_IN="${DIR}/$CFC_BASE" + +TOOL_OUT="${CFC_DIR}/${CFC_BASE}-${TOOL_USER}" +RULE_OUT="${RULE_DIR}/10-${RULE_BASE}-${TOOL_USER}.rules" +ACTION_ID="${RULE_BASE}.${TOOL_USER}" +ACTION_OUT="/usr/share/polkit-1/actions/${ACTION_ID}.policy" + +function print_policy_xml() { + sed -e "s:{{PATH}}:${TOOL_OUT}:g" \ + -e "s:{{ACTION_BASE}}:${ACTION_BASE}:g" \ + -e "s:{{ACTION_ID}}:${ACTION_ID}:g" "${ACTION_IN}" +} + +function print_rules_javascript() { + if [[ "$RULE_IN" == *.legacy ]]; then + sed -e "s:{{RULE_BASE}}:${RULE_BASE}:g" "${RULE_IN}" + else + sed -e "s:{{TOOL_OUT}}:${TOOL_OUT}:g" \ + -e "s:{{TOOL_USER}}:${TOOL_USER}:g" "${RULE_IN}" + fi + +} + +if [ "$ACTION" = "supported" ] +then + check_support +fi + +if [ "$ACTION" = "check" ] +then + if ! print_rules_javascript | cmp --silent "${RULE_OUT}" + then + if [ -f "${ACTION_OUT}" ] + then + echo "Your $EXTENSION_NAME installation needs updating!" + exit ${EXIT_NEEDS_UPDATE} + else + echo "Not installed" + exit ${EXIT_NOT_INSTALLED} + fi + fi + echo "Installed" + + exit ${EXIT_SUCCESS} +fi + +TOOL_NAME=$(basename ${TOOL_OUT}) + +if [ "$ACTION" = "install" ] +then + if [ "${EUID}" -ne 0 ]; then + echo "The install action must be run as root for security reasons!" + echo "Please have a look at https://github.com/martin31821/cpupower/issues/102" + echo "for further details." + exit ${EXIT_MUST_BE_ROOT} + fi + + echo -n "$(gtxt 'Installing') ${TOOL_NAME} $(gtxt 'tool')... " + mkdir -p "${CFC_DIR}" + install "${TOOL_IN}" "${TOOL_OUT}" || fail + success + + if [ ! -z "$ACTION_IN" ];then + echo "$(gtxt 'Using legacy policykit install')..." + echo -n "$(gtxt 'Installing') $(gtxt 'policykit action')..." + (print_policy_xml > "${ACTION_OUT}" 2>/dev/null && chmod 0644 "${ACTION_OUT}") || fail + success + fi + + echo -n "$(gtxt 'Installing') $(gtxt 'policykit rule')..." + mkdir -p "${RULE_DIR}" + (print_rules_javascript > "${RULE_OUT}" 2>/dev/null && chmod 0644 "${RULE_OUT}") || fail + success + + exit ${EXIT_SUCCESS} +fi + +if [ "$ACTION" = "update" ] +then + "${BASH_SOURCE[0]}" --tool-user "${TOOL_USER}" uninstall || exit $? + "${BASH_SOURCE[0]}" --tool-user "${TOOL_USER}" install || exit $? + + exit ${EXIT_SUCCESS} +fi + +if [ "$ACTION" = "uninstall" ] +then + LEG_CFG_OUT="/usr/bin/shutdowntimerctl-$TOOL_USER" + if [ -f "$LEG_CFG_OUT" ] + then + # remove legacy "tool" install + echo -n "$(gtxt 'Uninstalling') $(gtxt 'tool')..." + rm "${LEG_CFG_OUT}" || fail " - $(gtxt 'cannot remove') ${LEG_CFG_OUT}" && success + fi + + if [ -f "$ACTION_OUT" ] + then + # remove legacy "policykit action" install + echo -n "$(gtxt 'Uninstalling') $(gtxt 'policykit action')..." + rm "${ACTION_OUT}" || fail " - $(gtxt 'cannot remove') ${ACTION_OUT}" && success + fi + LEG_RULE_OUT="/usr/share/polkit-1/rules.d/10-dem.shutdowntimer.settimers.rules" + if [ -f "$LEG_RULE_OUT" ] + then + # remove legacy "policykit action" install + echo -n "$(gtxt 'Uninstalling') $(gtxt 'policykit rule')..." + rm "${LEG_RULE_OUT}" || fail " - $(gtxt 'cannot remove') ${LEG_RULE_OUT}" && success + fi + + echo -n "$(gtxt 'Uninstalling') ${TOOL_NAME} $(gtxt 'tool')... " + if [ -f "${TOOL_OUT}" ] + then + rm "${TOOL_OUT}" || fail " - $(gtxt 'cannot remove') ${TOOL_OUT}" && success + else + echo "$(gtxt 'tool') $(gtxt 'not installed at') ${TOOL_OUT}" + fi + + echo -n "$(gtxt 'Uninstalling') $(gtxt 'policykit rule')... " + if [ -f "${RULE_OUT}" ] + then + rm "${RULE_OUT}" || fail " - $(gtxt 'cannot remove') ${RULE_OUT}" && success + else + echo "$(gtxt 'policy rule') $(gtxt 'not installed at') ${RULE_OUT}" + fi + + exit ${EXIT_SUCCESS} +fi + +echo "Unknown parameter." +usage + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/shutdowntimerctl b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/shutdowntimerctl new file mode 100644 index 0000000..f11c673 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/tool/shutdowntimerctl @@ -0,0 +1,53 @@ +#!/bin/bash + +# shutdowntimerctl - This script can configure the shutdown and rtc wake alarm schedule. +# +# This file is part of the gnome-shell extension ShutdownTimer@Deminder. + +SHUTDOWN_BIN=/usr/sbin/shutdown +RTCWAKE_BIN=/usr/sbin/rtcwake + +SHUTDOWN_MODE="-P" +if [ ! -z "$2" ] && [ "$2" -gt 0 ];then + POSITIVE_VALUE="$2" +fi + +function print_help() { + echo "[help] (show this help)" >&2 + echo "[shutdown|reboot] {MINUTES}" >&2 + echo "[wake|wake-cancel] {MINUTES} (default: 0)" >&2 +} + +if [ "$#" -lt 1 ]; then + print_help + exit +fi + +case "$1" in + shutdown|reboot) + if [[ "$1" = "reboot" ]]; then + SHUTDOWN_MODE="-r" + fi + $SHUTDOWN_BIN "$SHUTDOWN_MODE" "$POSITIVE_VALUE" + ;; + shutdown-cancel) + $SHUTDOWN_BIN -c + ;; + wake|wake-cancel) + if [ -z "$POSITIVE_VALUE" ];then + $RTCWAKE_BIN --mode disable + else + $RTCWAKE_BIN --date +${POSITIVE_VALUE}min --mode on & + PID=$! + sleep 0.2 + kill $PID + fi + ;; + -h|help) + print_help + ;; + *) + echo "Invalid argument: $1" >&2 + print_help +esac + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/ui/prefs.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/ui/prefs.ui new file mode 100644 index 0000000..be8197f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/ShutdownTimer@deminder/ui/prefs.ui @@ -0,0 +1,456 @@ + + + + + START test +. +. +. +. +. +. +. +. +. +. +. +. +DONE test + + + + 1000000 + 1 + 10 + + + -5 + 5 + 0.001 + 0.10 + + + -5 + 5 + 0.001 + 0.10 + + + + 10000 + 1 + 10 + + + 100 + 0.1 + 10 + + + 10000 + 1 + 10 + + + 100 + 0.1 + 10 + + + shutdowntimer-prefs-install + Install + go-up-symbolic + + + + + 1 + Install/Uninstall privileges for this user + Setup a privileged script and give user access via polkit + + + center + + + + + + + Install output + + + 1 + installer_scrollbar_adjustment + 350 + + + 1 + 5 + 0 + char + 0 + install_log_textbuffer + 0 + 1 + + + + + + + + + + + shutdowntimer-prefs-shutdown + Shutdown + preferences-system-time-symbolic + + + Timer Action + + + Use mode + Mode to use for timer action + + + center + 0 + + Shutdown + Suspend + Reboot + (replaced in code) + + + + + + + + Show end-session dialog + Shown for reboot and shutdown if screensaver is inactive + + + center + + + + + + + Toggle root shutdown with shutdown timer + Runs extra 'shutdown -P/-r' command for shutdown or reboot + + + center + + + + + + + + + Timer Input + + + Shutdown slider position (in &#37;) + + + 1 + center + shutdown_slider_adjustment + 1 + 1 + 1 + 1 + if-valid + + + + + + + Shutdown slider position (in &#37;) + + + 1 + center + 1 + shutdown_slider_adjustment + 1 + 1 + 1 + + + + + + + Non-linear scaling or 0 to disable + + + 1 + center + nonlinear_shutdown_slider_adjustment + 1 + 3 + 1 + 1 + if-valid + 120 + + + + + + + Maximum shutdown timer value (in minutes) + + + 1 + center + shutdown_max_timer_adjustment + 1 + 1 + 1 + if-valid + 120 + + + + + + + + + shutdowntimer-prefs-wake + Wake + alarm-symbolic + + + Timer Action + + + 1 + Toggle wake with timer action + + + 1 + center + + + + + + + + + Timer Input + + + Wake slider position (in &#37;) + + + 1 + center + wake_slider_adjustment + 1 + 1 + 1 + 1 + if-valid + + + + + + + Wake slider position (in &#37;) + + + 1 + center + 1 + wake_slider_adjustment + 1 + 1 + 1 + + + + + + + Non-linear scaling or 0 to disable + + + 1 + center + nonlinear_wake_slider_adjustment + 1 + 3 + 1 + 1 + if-valid + 120 + + + + + + + Maximum wake timer value (in minutes) + + + 1 + center + wake_max_timer_adjustment + 1 + 1 + 1 + if-valid + 120 + + + + + + + + + shutdowntimer-prefs-display + Display + preferences-color-symbolic + + + General + + + 1 + Show settings button + + + center + + + + + + + 1 + Show notification text boxes + + + center + 1 + + + + + + + + + Shutdown + + + Show shutdown items + Comma-separated shutdown modes which are shown in the popup menu + + + + + Show shutdown items + + + center + show_shutdown_mode_buffer + poweroff, reboot, suspend + + + + + + + 1 + Show shutdown slider + + + center + + + + + + + + + Wake + + + 1 + Show wake items + + + center + + + + + + + 1 + Show wake slider + + + center + + + + + + + + + shutdowntimer-prefs-check + Check + emblem-ok-symbolic + + + + + 1 + Enable check + Script is run in a bash user shell after timer activates. Timer action proceeds if check terminates successfully. + + + center + + + + + + + Check script + + + 1 + 350 + + + 1 + 5 + check_command_textbuffer + 1 + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/LICENSE b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/LICENSE new file mode 100644 index 0000000..d7f1051 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This 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. diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/extension.js new file mode 100644 index 0000000..40df84a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/extension.js @@ -0,0 +1,564 @@ +const {Clutter, Gio, St, GObject} = imports.gi; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const Main = imports.ui.main; +const Util = imports.misc.util; +const Mainloop = imports.mainloop; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const Sensors = Me.imports.sensors; +const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']); +const _ = Gettext.gettext; +const MessageTray = imports.ui.messageTray; +const Values = Me.imports.values; +const Config = imports.misc.config; +const MenuItem = Me.imports.menuItem; + +let vitalsMenu; + +var VitalsMenuButton = GObject.registerClass({ + GTypeName: 'VitalsMenuButton', +}, class VitalsMenuButton extends PanelMenu.Button { + _init() { + super._init(St.Align.START); + + this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.vitals'); + + this._sensorIcons = { + 'temperature' : { 'icon': 'temperature-symbolic.svg' }, + 'voltage' : { 'icon': 'voltage-symbolic.svg' }, + 'fan' : { 'icon': 'fan-symbolic.svg' }, + 'memory' : { 'icon': 'memory-symbolic.svg' }, + 'processor' : { 'icon': 'cpu-symbolic.svg' }, + 'system' : { 'icon': 'system-symbolic.svg' }, + 'network' : { 'icon': 'network-symbolic.svg', + 'icon-rx': 'network-download-symbolic.svg', + 'icon-tx': 'network-upload-symbolic.svg' }, + 'storage' : { 'icon': 'storage-symbolic.svg' }, + 'battery' : { 'icon': 'battery-symbolic.svg' } + } + + this._warnings = []; + this._sensorMenuItems = {}; + this._hotLabels = {}; + this._hotIcons = {}; + this._groups = {}; + this._widths = {}; + this._last_query = new Date().getTime(); + + this._sensors = new Sensors.Sensors(this._settings, this._sensorIcons); + this._values = new Values.Values(this._settings, this._sensorIcons); + this._menuLayout = new St.BoxLayout({ + vertical: false, + clip_to_allocation: true, + x_align: Clutter.ActorAlign.START, + y_align: Clutter.ActorAlign.CENTER, + reactive: true, + x_expand: true, + pack_start: false + }); + + this._drawMenu(); + this.add_actor(this._menuLayout); + this._settingChangedSignals = []; + this._refreshTimeoutId = null; + + this._addSettingChangedSignal('update-time', this._updateTimeChanged.bind(this)); + this._addSettingChangedSignal('position-in-panel', this._positionInPanelChanged.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' ]; + for (let setting of Object.values(settings)) + this._addSettingChangedSignal(setting, this._redrawMenu.bind(this)); + + // add signals for show- preference based categories + for (let sensor in this._sensorIcons) + this._addSettingChangedSignal('show-' + sensor, this._showHideSensorsChanged.bind(this)); + + this._initializeMenu(); + + // start off with fresh sensors + this._querySensors(); + + // start monitoring sensors + this._initializeTimer(); + } + + _initializeMenu() { + // display sensor categories + for (let sensor in this._sensorIcons) { + // 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(Me.path + '/icons/' + this._sensorIcons[sensor]['icon']); + + // 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]); + } + + // add separator + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + + let item = new PopupMenu.PopupBaseMenuItem({ + reactive: false, + style_class: 'vitals-menu-button-container' + }); + + let customButtonBox = new St.BoxLayout({ + style_class: 'vitals-button-box', + vertical: false, + clip_to_allocation: true, + x_align: Clutter.ActorAlign.CENTER, + y_align: Clutter.ActorAlign.CENTER, + reactive: true, + x_expand: true, + pack_start: false + }); + + // custom round refresh button + let refreshButton = this._createRoundButton('view-refresh-symbolic', _('Refresh')); + refreshButton.connect('clicked', (self) => { + // force refresh by clearing history + this._sensors.resetHistory(); + this._values.resetHistory(); + + // make sure timer fires at next full interval + this._updateTimeChanged(); + + // refresh sensors now + this._querySensors(); + }); + customButtonBox.add_actor(refreshButton); + + // custom round monitor button + let monitorButton = this._createRoundButton('org.gnome.SystemMonitor-symbolic', _('System Monitor')); + monitorButton.connect('clicked', (self) => { + this.menu._getTopMenu().close(); + Util.spawn([this._settings.get_string('monitor-cmd')]); + }); + customButtonBox.add_actor(monitorButton); + + // custom round preferences button + let prefsButton = this._createRoundButton('preferences-system-symbolic', _('Preferences')); + prefsButton.connect('clicked', (self) => { + this.menu._getTopMenu().close(); + ExtensionUtils.openPrefs(); + }); + customButtonBox.add_actor(prefsButton); + + // now add the buttons to the top bar + item.actor.add_actor(customButtonBox); + + // add buttons + this.menu.addMenuItem(item); + + // query sensors on menu open + this._menuStateChangeId = this.menu.connect('open-state-changed', (self, isMenuOpen) => { + if (isMenuOpen) { + // make sure timer fires at next full interval + this._updateTimeChanged(); + + // refresh sensors now + this._querySensors(); + } + }); + } + + _createRoundButton(iconName) { + let button = new St.Button({ + style_class: 'message-list-clear-button button vitals-button-action' + }); + + button.child = new St.Icon({ + icon_name: iconName + }); + + return button; + } + + _removeMissingHotSensors(hotSensors) { + for (let i = hotSensors.length - 1; i >= 0; i--) { + let sensor = hotSensors[i]; + + // make sure default icon (if any) stays visible + if (sensor == '_default_icon_') continue; + + // removes sensors that are no longer available + if (!this._sensorMenuItems[sensor]) { + hotSensors.splice(i, 1); + this._removeHotLabel(sensor); + this._removeHotIcon(sensor); + } + } + + return hotSensors; + } + + _saveHotSensors(hotSensors) { + // removes any sensors that may not currently be available + hotSensors = this._removeMissingHotSensors(hotSensors); + + this._settings.set_strv('hot-sensors', hotSensors.filter( + function(item, pos) { + return hotSensors.indexOf(item) == pos; + } + )); + } + + _initializeTimer() { + // used to query sensors and update display + let update_time = this._settings.get_int('update-time'); + this._refreshTimeoutId = Mainloop.timeout_add_seconds(update_time, (self) => { + // only update menu if we have hot sensors + if (Object.values(this._hotLabels).length > 0) + this._querySensors(); + + // keep the timer running + return true; + }); + } + + _createHotItem(key, value) { + let icon = this._defaultIcon(key); + this._hotIcons[key] = icon; + this._menuLayout.add_actor(icon) + + // don't add a label when no sensors are in the panel + if (key == '_default_icon_') return; + + let label = new St.Label({ + style_class: 'vitals-panel-label', + text: (value)?value:'\u2026', // ... + y_expand: true, + y_align: Clutter.ActorAlign.START + }); + + // attempt to prevent ellipsizes + label.get_clutter_text().ellipsize = 0; + + this._hotLabels[key] = label; + + // support for fixed widths #55, save label (text) width + this._widths[key] = label.width; + + this._menuLayout.add_actor(label); + } + + _showHideSensorsChanged(self, sensor) { + this._sensors.resetHistory(); + this._groups[sensor.substr(5)].visible = this._settings.get_boolean(sensor); + } + + _positionInPanelChanged() { + this.container.get_parent().remove_actor(this.container); + let position = this._positionInPanel(); + + // allows easily addressable boxes + let boxes = { + left: Main.panel._leftBox, + center: Main.panel._centerBox, + right: Main.panel._rightBox + }; + + // update position when changed from preferences + boxes[position[0]].insert_child_at_index(this.container, position[1]); + } + + _removeHotLabel(key) { + if (key in this._hotLabels) { + let label = this._hotLabels[key]; + delete this._hotLabels[key]; + // make sure set_label is not called on non existant actor + label.destroy(); + } + } + + _removeHotLabels() { + for (let key in this._hotLabels) + this._removeHotLabel(key); + } + + _removeHotIcon(key) { + if (key in this._hotIcons) { + this._hotIcons[key].destroy(); + delete this._hotIcons[key]; + } + } + + _removeHotIcons() { + for (let key in this._hotIcons) + this._removeHotIcon(key); + } + + _redrawMenu() { + this._removeHotIcons(); + this._removeHotLabels(); + + for (let key in this._sensorMenuItems) { + if (key.includes('-group')) continue; + this._sensorMenuItems[key].destroy(); + delete this._sensorMenuItems[key]; + } + + this._drawMenu(); + this._sensors.resetHistory(); + this._values.resetHistory(); + this._querySensors(); + } + + _drawMenu() { + // grab list of selected menubar icons + let hotSensors = this._settings.get_strv('hot-sensors'); + for (let key of Object.values(hotSensors)) { + // fixes issue #225 which started when _max_ was moved to the end + if (key == '__max_network-download__') key = '__network-rx_max__'; + if (key == '__max_network-upload__') key = '__network-tx_max__'; + + this._createHotItem(key); + } + } + + _destroyTimer() { + // invalidate and reinitialize timer + if (this._refreshTimeoutId != null) { + Mainloop.source_remove(this._refreshTimeoutId); + this._refreshTimeoutId = null; + } + } + + _updateTimeChanged() { + this._destroyTimer(); + this._initializeTimer(); + } + + _addSettingChangedSignal(key, callback) { + this._settingChangedSignals.push(this._settings.connect('changed::' + key, callback)); + } + + _updateDisplay(label, value, type, key) { + // update sensor value in menubar + if (this._hotLabels[key]) { + this._hotLabels[key].set_text(value); + + // support for fixed widths #55 + if (this._settings.get_boolean('fixed-widths')) { + // grab text box width and see if new text is wider than old text + let width2 = this._hotLabels[key].get_clutter_text().width; + if (width2 > this._widths[key]) { + this._hotLabels[key].set_width(width2); + this._widths[key] = width2; + } + } + } + + // have we added this sensor before? + let item = this._sensorMenuItems[key]; + if (item) { + // update sensor value in the group + item.value = value; + } else if (type.includes('-group')) { + // update text next to group header + let group = type.split('-')[0]; + if (this._groups[group]) { + this._groups[group].status.text = value; + this._sensorMenuItems[type] = this._groups[group]; + } + } else { + // add item to group for the first time + let sensor = { 'label': label, 'value': value, 'type': type } + this._appendMenuItem(sensor, key); + } + } + + _appendMenuItem(sensor, key) { + 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(Me.path + '/icons/' + this._sensorIcons[type][icon]); + + let item = new MenuItem.MenuItem(gicon, key, sensor.label, sensor.value, this._hotLabels[key]); + item.connect('toggle', (self) => { + let hotSensors = this._settings.get_strv('hot-sensors'); + + if (self.checked) { + // add selected sensor to panel + hotSensors.push(self.key); + this._createHotItem(self.key, self.value); + } else { + // remove selected sensor from panel + hotSensors.splice(hotSensors.indexOf(self.key), 1); + this._removeHotLabel(self.key); + this._removeHotIcon(self.key); + } + + if (hotSensors.length <= 0) { + // add generic icon to panel when no sensors are selected + hotSensors.push('_default_icon_'); + this._createHotItem('_default_icon_'); + } else { + let defIconPos = hotSensors.indexOf('_default_icon_'); + if (defIconPos >= 0) { + // remove generic icon from panel when sensors are selected + hotSensors.splice(defIconPos, 1); + this._removeHotIcon('_default_icon_'); + } + } + + // this code is called asynchronously - make sure to save it for next round + this._saveHotSensors(hotSensors); + }); + + this._sensorMenuItems[key] = item; + let i = Object.keys(this._sensorMenuItems[key]).length; + + // alphabetize the sensors for these categories + if (this._settings.get_boolean('alphabetize')) { + let menuItems = this._groups[type].menu._getMenuItems(); + for (i = 0; i < menuItems.length; i++) + // use natural sort order for system load, etc + if (menuItems[i].label.localeCompare(item.label, undefined, { numeric: true, sensitivity: 'base' }) > 0) + break; + } + + this._groups[type].menu.addMenuItem(item, i); + } + + _defaultLabel() { + return new St.Label({ + y_expand: true, + y_align: Clutter.ActorAlign.CENTER + }); + } + + _defaultIcon(key) { + let split = key.replaceAll('_', ' ').trim().split(' ')[0].split('-'); + let type = split[0]; + + let icon = new St.Icon({ + style_class: 'system-status-icon vitals-panel-icon-' + type, + reactive: true + }); + + // 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(Me.path + '/icons/' + this._sensorIcons['system']['icon']); + } 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(Me.path + '/icons/' + this._sensorIcons[type][iconObj]); + } + + return icon; + } + + _ucFirst(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + } + + _positionInPanel() { + let alignment = ''; + let gravity = 0; + let arrow_pos = 0; + + switch (this._settings.get_int('position-in-panel')) { + case 0: // left + alignment = 'left'; + gravity = -1; + arrow_pos = 1; + break; + case 1: // center + alignment = 'center'; + gravity = -1; + arrow_pos = 0.5; + break; + case 2: // right + alignment = 'right'; + gravity = 0; + arrow_pos = 0; + break; + case 3: // far left + alignment = 'left'; + gravity = 0; + arrow_pos = 1; + break; + case 4: // far right + alignment = 'right'; + gravity = -1; + arrow_pos = 0; + break; + } + + // set arrow position when initializing and moving vitals + this.menu._arrowAlignment = arrow_pos; + + return [alignment, gravity]; + } + + _querySensors() { + // figure out last run time + let now = new Date().getTime(); + let dwell = (now - this._last_query) / 1000; + this._last_query = now; + + this._sensors.query((label, value, type, format) => { + let key = '_' + type.replace('-group', '') + '_' + label.replace(' ', '_').toLowerCase() + '_'; + + // if a sensor is disabled, gray it out + if (key in this._sensorMenuItems) { + this._sensorMenuItems[key].setSensitive((value!='disabled')); + + // don't continue below, last known value is shown + if (value == 'disabled') return; + } + + 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 (this._warnings.length > 0) { + this._notify('Vitals', this._warnings.join("\n"), 'folder-symbolic'); + this._warnings = []; + } + } + + _notify(msg, details, icon) { + let source = new MessageTray.Source('MyApp Information', icon); + Main.messageTray.add(source); + let notification = new MessageTray.Notification(source, msg, details); + notification.setTransient(true); + source.notify(notification); + } + + destroy() { + this._destroyTimer(); + + for (let signal of Object.values(this._settingChangedSignals)) + this._settings.disconnect(signal); + + super.destroy(); + } +}); + +function init() { + ExtensionUtils.initTranslations('vitals'); +} + +function enable() { + vitalsMenu = new VitalsMenuButton(); + let position = vitalsMenu._positionInPanel(); + Main.panel.addToStatusArea('vitalsMenu', vitalsMenu, position[1], position[0]); +} + +function disable() { + vitalsMenu.destroy(); + vitalsMenu = null; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/file.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/file.js new file mode 100644 index 0000000..594325f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/file.js @@ -0,0 +1,85 @@ +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +Me.imports.helpers.polyfills; +const ByteArray = imports.byteArray; + +function getcontents(filename) { + let handle = Gio.File.new_for_path(filename); + let contents = handle.load_contents(null)[1]; + return ByteArray.toString(contents).trim(); +} + +function File(path) { + if (path.indexOf('https://') == -1) + this.file = Gio.File.new_for_path(path); + else + this.file = Gio.File.new_for_uri(path); +} + +File.prototype.read = function(delimiter = '', strip_header = false) { + return new Promise((resolve, reject) => { + try { + this.file.load_contents_async(null, function(file, res) { + try { + // grab contents of file or website + let contents = file.load_contents_finish(res)[1]; + + // convert contents to string + contents = ByteArray.toString(contents).trim(); + + // split contents by delimiter if passed in + if (delimiter) contents = contents.split(delimiter); + + // optionally strip header when converting to a list + if (strip_header) contents.shift(); + + // return results + resolve(contents); + } catch (e) { + reject(e.message); + } + }); + } catch (e) { + reject(e.message); + } + }); +}; + +File.prototype.list = function() { + return new Promise((resolve, reject) => { + let max_items = 125, results = []; + + try { + this.file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, function(file, res) { + try { + let enumerator = file.enumerate_children_finish(res); + + let callback = function(enumerator, res) { + try { + let files = enumerator.next_files_finish(res); + for (let i = 0; i < files.length; i++) { + results.push(files[i].get_attribute_as_string(Gio.FILE_ATTRIBUTE_STANDARD_NAME)); + } + + if (files.length == 0) { + enumerator.close_async(GLib.PRIORITY_LOW, null, function(){}); + resolve(results); + } else { + enumerator.next_files_async(max_items, GLib.PRIORITY_LOW, null, callback); + } + } catch (e) { + reject(e.message); + } + }; + + enumerator.next_files_async(max_items, GLib.PRIORITY_LOW, null, callback); + } catch (e) { + reject(e.message); + } + }); + } catch (e) { + reject(e.message); + } + }); +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/polyfills.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/polyfills.js new file mode 100644 index 0000000..1ad274f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/helpers/polyfills.js @@ -0,0 +1,184 @@ +if (!String.prototype.includes) { + String.prototype.includes = function(search, start) { + 'use strict'; + + if (typeof start !== 'number') + start = 0; + + if (start + search.length > this.length) + return false; + else + return this.indexOf(search, start) !== -1; + } +} + +// in parts of the system you may think that we can use Object.values +// instead of "key in" statements. Gnome 3.18 - 3.22 doesn't like doing that. +if (!Object.values) + Object.values = obj => Object.keys(obj).map(key => obj[key]); + +if (!Math.getMaxOfArray) { + Math.getMaxOfArray = function(numArray) { + return Math.max.apply(null, numArray); + } +} + +// newer verisons of Gnome have Promises built in +// Credit goes to https://github.com/satya164/gjs-helpers +if (typeof Promise === 'undefined') { + const GLib = imports.gi.GLib; + + const PENDING = 0, + FULFILLED = 1, + REJECTED = 2; + + Promise = function(executor) { + if (false === (this instanceof Promise)) { + throw new TypeError("Promises must be constructed via new"); + } + + if (typeof executor !== "function") { + throw new TypeError("Promise resolver " + executor + " is not a function"); + } + + // Create an array to add handlers + this._deferreds = []; + + // Set the promise status + this._state = PENDING; + this._caught = false; + + this._handle = deferred => { + if (this._state === PENDING) { + this._deferreds.push(deferred); + + return; + } + + GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1, () => { + let cb = this._state === FULFILLED ? deferred.onFulfilled : deferred.onRejected; + + if (cb === null) { + (this._state === FULFILLED ? deferred.resolve : deferred.reject)(this._value); + + return false; + } + + if (typeof cb !== "function") { + deferred.reject(this._value); + + return false; + } + + let ret; + + try { + ret = cb(this._value); + } catch (e) { + deferred.reject(e); + + return false; + } + + deferred.resolve(ret); + + return false; // Don't repeat + }); + }; + + let doresolve = (fn, onFulfilled, onRejected) => { + let done = false; + + try { + fn(value => { + if (done) { + return; + } + + done = true; + + onFulfilled(value); + }, function(reason) { + if (done) return; + done = true; + onRejected(reason); + }); + } catch (e) { + if (done) return; + done = true; + onRejected(e); + } + }; + + let finale = () => { + for (var i = 0, len = this._deferreds.length; i < len; i++) { + this._handle.call(this, this._deferreds[i]); + } + + this._deferreds = null; + }; + + let resolve = value => { + // Call all fulfillment handlers one by one + try { + if (value === this) { + throw new TypeError("A promise cannot be resolved with itself"); + } + + if (value && (typeof value === "object" || typeof value === "function")) { + // If returned value is a thenable, treat is as a promise + if (typeof value.then === "function") { + doresolve(value.then.bind(value), resolve.bind(this), reject.bind(this)); + + return; + } + } + + // Promise is fulfilled + this._state = FULFILLED; + this._value = value; + + finale.call(this); + } catch (e) { + reject.call(this, e); + } + }; + + let reject = reason => { + // Promise is rejected + this._state = REJECTED; + this._value = reason; + + finale.call(this); + }; + + doresolve(executor, resolve.bind(this), reject.bind(this)); + }; + + // Appends fulfillment and rejection handlers to the promise + Promise.prototype.then = function(onFulfilled, onRejected) { + return new Promise((resolve, reject) => { + this._handle.call(this, { + resolve: resolve, + reject: reject, + onFulfilled: onFulfilled, + onRejected: onRejected + }); + }); + }; + + // Appends a rejection handler callback to the promise + Promise.prototype.catch = function(onRejected) { + return this.then(null, onRejected); + }; + + // Returns a Promise object that is rejected with the given reason + Promise.reject = function(reason) { + return new Promise((resolve, reject) => reject(reason)); + }; + + // Returns a Promise object that is resolved with the given value + Promise.resolve = function(value) { + return new Promise(resolve => resolve(value)); + }; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg new file mode 100644 index 0000000..70df9ee --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg new file mode 100644 index 0000000..19969e4 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg new file mode 100644 index 0000000..a584b74 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg @@ -0,0 +1,133 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg new file mode 100644 index 0000000..13ca4bc --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg new file mode 100644 index 0000000..5cab840 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg new file mode 100644 index 0000000..0483417 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg new file mode 100644 index 0000000..e2c5a08 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg new file mode 100644 index 0000000..9832999 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg new file mode 100644 index 0000000..909f530 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg new file mode 100644 index 0000000..c58beca --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg @@ -0,0 +1,45 @@ + +image/svg+xml \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg new file mode 100644 index 0000000..b2e7eff --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg @@ -0,0 +1,125 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..5a18109 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/cs/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/cs/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..cef0cc7 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/cs/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/es/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/es/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..4cf48ae Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/es/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..38454e3 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fr/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fr/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..0bbb62b Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/fr/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..8d9429b Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/nl/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/nl/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..476fd4d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/nl/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..ef097f7 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..0c3ba94 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..ebf4c11 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..6fb58f5 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..21039f2 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..5204308 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..a7cc350 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..fcc6505 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/zh_CN/LC_MESSAGES/vitals.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/zh_CN/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000..5c43dc8 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/locale/zh_CN/LC_MESSAGES/vitals.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/menuItem.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/menuItem.js new file mode 100644 index 0000000..0dd51b7 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/menuItem.js @@ -0,0 +1,77 @@ +const St = imports.gi.St; +const PopupMenu = imports.ui.popupMenu; +const GObject = imports.gi.GObject; +const Clutter = imports.gi.Clutter; + +var MenuItem = GObject.registerClass({ + + Signals: { + 'toggle': { param_types: [Clutter.Event.$gtype] }, + }, + +}, class MenuItem extends PopupMenu.PopupBaseMenuItem { + + _init(icon, key, label, value, checked) { + super._init({ reactive: true }); + + this._checked = checked; + this._updateOrnament(); + + this._key = key; + this._gIcon = icon; + + // add icon + this.add(new St.Icon({ style_class: 'popup-menu-icon', gicon : this._gIcon })); + + // add label + this._labelActor = new St.Label({ text: label }); + this.add(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.actor._delegate = this; + } + + get checked() { + return this._checked; + } + + get key() { + return this._key; + } + + get gicon() { + return this._gIcon; + } + + set value(value) { + this._valueLabel.text = value; + } + + get value() { + return this._valueLabel.text; + } + + // prevents menu from being closed + activate(event) { + this._checked = !this._checked; + this._updateOrnament(); + this.emit('toggle', event); + } + + _updateOrnament() { + if (this._checked) + this.setOrnament(PopupMenu.Ornament.CHECK); + else + this.setOrnament(PopupMenu.Ornament.NONE); + } + + get label() { + return this._labelActor.text; + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/metadata.json new file mode 100644 index 0000000..30d6ff1 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/metadata.json @@ -0,0 +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.", + "gettext-domain": "vitals", + "name": "Vitals", + "settings-schema": "org.gnome.shell.extensions.vitals", + "shell-version": [ + "3.38", + "40", + "41", + "42", + "43" + ], + "url": "https://github.com/corecoding/Vitals", + "uuid": "Vitals@CoreCoding.com", + "version": 57 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.js new file mode 100644 index 0000000..4a987de --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.js @@ -0,0 +1,149 @@ +// https://gjs.guide/extensions/upgrading/gnome-shell-40.html#contents +const Config = imports.misc.config; +const [major] = Config.PACKAGE_VERSION.split('.'); +const shellVersion = Number.parseInt(major); +const {Gio, Gtk, GObject} = imports.gi; +const Mainloop = imports.mainloop; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const ExtensionUtils = imports.misc.extensionUtils; +const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']); +const _ = Gettext.gettext; + +/* + if (sensor == 'show-storage' && this._settings.get_boolean(sensor)) { + + let val = true; + + try { + let GTop = imports.gi.GTop; + } catch (e) { + val = false; + } + + let now = new Date().getTime(); + this._notify("Vitals", "Please run sudo apt install gir1.2-gtop-2.0", 'folder-symbolic'); + + } +*/ + +const Settings = new GObject.Class({ + Name: 'Vitals.Settings', + + _init: function(params) { + this.parent(params); + + this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.vitals'); + + this.builder = new Gtk.Builder(); + this.builder.set_translation_domain(Me.metadata['gettext-domain']); + + if (shellVersion < 40) + this.builder.add_from_file(Me.path + '/prefs.legacy.ui'); + else + this.builder.add_from_file(Me.path + '/prefs.ui'); + + this.widget = this.builder.get_object('prefs-container'); + + this._bind_settings(); + }, + + // Bind the gtk window to the schema settings + _bind_settings: function() { + let widget; + + // process sensor toggles + let sensors = [ 'show-temperature', 'show-voltage', 'show-fan', + 'show-memory', 'show-processor', 'show-system', + 'show-network', 'show-storage', 'use-higher-precision', + 'alphabetize', 'hide-zeros', 'include-public-ip', + 'show-battery', 'fixed-widths', 'hide-icons' ]; + + for (let key in sensors) { + let sensor = sensors[key]; + + widget = this.builder.get_object(sensor); + widget.set_active(this._settings.get_boolean(sensor)); + widget.connect('state-set', (_, val) => { + this._settings.set_boolean(sensor, val); + }); + } + + // process individual drop down sensor preferences + sensors = [ 'position-in-panel', 'unit', 'network-speed-format', 'memory-measurement', 'storage-measurement', 'battery-slot' ]; + for (let key in sensors) { + let sensor = sensors[key]; + + widget = this.builder.get_object(sensor); + widget.set_active(this._settings.get_int(sensor)); + widget.connect('changed', (widget) => { + this._settings.set_int(sensor, widget.get_active()); + }); + } + + this._settings.bind('update-time', this.builder.get_object('update-time'), 'value', Gio.SettingsBindFlags.DEFAULT); + + // process individual text entry sensor preferences + sensors = [ 'storage-path', 'monitor-cmd' ]; + for (let key in sensors) { + let sensor = sensors[key]; + + widget = this.builder.get_object(sensor); + widget.set_text(this._settings.get_string(sensor)); + + widget.connect('changed', (widget) => { + let text = widget.get_text(); + if (!text) text = widget.get_placeholder_text(); + this._settings.set_string(sensor, text); + }); + } + + // makes individual sensor preference boxes appear + sensors = [ 'temperature', 'network', 'storage', 'memory', 'battery', 'system' ]; + for (let key in sensors) { + let sensor = sensors[key]; + + // create dialog for intelligent autohide advanced settings + this.builder.get_object(sensor + '-prefs').connect('clicked', () => { + let transientObj; + if (shellVersion < 40) + transientObj = this.widget.get_toplevel(); + else + transientObj = this.widget.get_root(); + + let title = sensor.charAt(0).toUpperCase() + sensor.slice(1); + let dialog = new Gtk.Dialog({ title: _(title + ' Preferences'), + transient_for: transientObj, + use_header_bar: false, + modal: true }); + + let box = this.builder.get_object(sensor + '_prefs'); + + if (shellVersion < 40) + dialog.get_content_area().add(box); + else + dialog.get_content_area().append(box); + + dialog.connect('response', (dialog, id) => { + // remove the settings box so it doesn't get destroyed; + dialog.get_content_area().remove(box); + dialog.destroy(); + return; + }); + + dialog.show(); + }); + } + } +}); + +function init() { + ExtensionUtils.initTranslations(); +} + +function buildPrefsWidget() { + let settings = new Settings(); + let widget = settings.widget; + + widget.show(); + return widget; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.legacy.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.legacy.ui new file mode 100644 index 0000000..b61ea2c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.legacy.ui @@ -0,0 +1,1669 @@ + + + + + + 1 + 60 + 1 + 10 + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + Include public IP address + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + Format + + + True + True + 0 + + + + + True + False + 0 + + Bytes + Bits + + + + False + True + end + 1 + + + + + + + + + + + + + + False + True + 0 + + + + + False + 6 + 6 + 6 + 6 + vertical + 2 + + + True + False + True + True + True + + + True + False + 12 + 9 + 12 + 12 + vertical + 12 + + + True + False + start + baseline + General + + + + + + False + True + 0 + + + + + True + False + 0 + out + + + True + False + none + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Seconds between updates + + + True + True + 0 + + + + + True + True + 5 + 5 + 2 + 2 + number + update-time-params + 1 + True + True + if-valid + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Position in panel + + + True + True + 0 + + + + + True + False + 5 + 0 + + Left + Center + Right + Far Left + Far Right + + + + False + True + end + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Use higher precision + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Alphabetize sensors + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Hide zero values + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Use fixed widths + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + 5 + Hide icons in top bar + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + + + + + + False + True + 1 + + + + + True + False + start + baseline + About + + + + + + False + True + 2 + + + + + True + False + 0 + out + + + True + False + start + baseline + 5 + 0 + 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. + True + True + 0 + + + + + + + + False + True + 3 + + + + + False + True + 0 + + + + + True + False + 6 + 9 + 12 + 12 + vertical + 12 + + + True + False + start + baseline + Sensors + + + + + + False + True + 6 + + + + + True + False + 0 + out + + + True + False + + + True + False + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor temperature + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor voltage + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor fan + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor memory + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor processor + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor system + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor network + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor storage + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + False + + + True + False + center + 6 + 6 + + + True + False + start + 5 + Monitor battery + + + True + True + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + + + + + + + + False + True + 7 + + + + + False + True + 1 + + + + + False + True + 1 + + + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + Monitor command + + + True + True + 0 + + + + + True + True + gnome-system-monitor + + + False + True + 1 + + + + + + + + + + + + + + False + True + 0 + + + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + Path + + + True + True + 0 + + + + + True + True + / + + + False + True + 1 + + + + + + + + + 100 + True + True + 0 + False + + + True + False + center + 6 + 6 + + + True + False + start + Measurement + + + True + True + 0 + + + + + True + False + 0 + + Binary + Decimal + + + + False + True + end + 1 + + + + + + + + + + + + + + False + True + 0 + + + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + 0 + False + + + True + False + center + 6 + 6 + + + True + False + start + Unit + + + True + True + 0 + + + + + True + False + 0 + + °C + °F + + + + False + True + end + 1 + + + + + + + + + + + + + + False + True + 0 + + + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + 0 + False + + + True + False + center + 6 + 6 + + + True + False + start + Measurement + + + True + True + 0 + + + + + True + False + 0 + + Binary + Decimal + + + + False + True + end + 1 + + + + + + + + + + + + + + False + True + 0 + + + + + True + False + 12 + 12 + vertical + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + False + + + True + False + 6 + 6 + + + True + False + start + Display battery + + + True + True + 0 + + + + + True + False + 0 + + BAT0 + BAT1 + BAT2 + CMB0 + + + + False + True + end + 1 + + + + + + + + + + + + + + False + True + 0 + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.ui new file mode 100644 index 0000000..9489261 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/prefs.ui @@ -0,0 +1,1111 @@ + + + + + 1 + 60 + 1 + 10 + + + 0 + 12 + 12 + 6 + 6 + vertical + + + 0 + + + 0 + none + + + 100 + 1 + 0 + + + 0 + 6 + 6 + 6 + 6 + 12 + + + 1 + 0 + start + Include public IP address + + + + + end + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + 6 + 6 + + + 1 + 0 + start + Format + + + + + 0 + 0 + + Bytes + Bits + + + + + + + + + + + + + + 0 + 0 + 6 + 6 + 6 + 6 + vertical + 2 + + + 0 + 1 + 1 + 1 + + + 0 + 12 + 9 + 12 + 12 + vertical + 12 + + + 0 + start + baseline + General + + + + + + + + 0 + + + 0 + none + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Seconds between updates + + + + + 5 + 5 + 0 + 2 + update-time-params + 1 + 1 + 1 + if-valid + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Position in panel + + + + + 0 + 5 + 0 + + Left + Center + Right + Far Left + Far Right + + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Use higher precision + + + + + end + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Alphabetize sensors + + + + + end + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Hide zero values + + + + + end + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Use fixed widths + + + + + end + + + + + + + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + Hide icons in top bar + + + + + end + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + 0 + 6 + 9 + 12 + 12 + vertical + 12 + + + 0 + start + baseline + Sensors + + + + + + + + 0 + + + 0 + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + Monitor temperature + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + Monitor voltage + + + + + end + + + + + + + + + 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 + + + + + end + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + 1 + 12 + 12 + 6 + 6 + vertical + + + 1 + + + 1 + none + + + 100 + 1 + 0 + + + 1 + 6 + 6 + 6 + 6 + 12 + + + 1 + 1 + start + Path + + + + + / + 1 + 1 + 24 + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + 6 + 6 + + + 1 + 0 + start + Measurement + + + + + 0 + 0 + + Binary + Decimal + + + + + + + + + + + + + + 0 + 12 + 12 + 6 + 6 + vertical + + + 0 + + + 0 + none + + + 100 + 1 + 0 + + + 0 + 6 + 6 + 6 + 6 + 12 + + + 1 + 0 + start + Unit + + + + + 0 + 0 + end + + °C + °F + + + + + + + + + + + + + + 0 + 12 + 12 + 6 + 6 + vertical + + + 0 + + + 0 + none + + + 100 + 1 + 0 + + + 0 + 6 + 6 + 6 + 6 + 12 + + + 1 + 0 + start + Measurement + + + + + 0 + 0 + + Binary + Decimal + + + + + + + + + + + + + + 0 + 12 + 12 + 6 + 6 + vertical + + + 0 + + + 0 + none + + + 100 + 1 + 0 + + + 0 + 6 + 6 + 6 + 6 + 12 + + + 1 + 0 + start + Display Battery + + + + + 0 + 0 + + BAT0 + BAT1 + BAT2 + CMB0 + + + + + + + + + + + + + + 1 + 12 + 12 + 6 + 6 + vertical + + + 1 + + + 1 + none + + + 100 + 1 + 0 + + + 1 + 6 + 6 + 6 + 6 + 12 + + + 1 + 1 + start + Monitor command + + + + + gnome-system-monitor + 1 + 1 + 24 + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled new file mode 100644 index 0000000..4606bde Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/sensors.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/sensors.js new file mode 100644 index 0000000..0595925 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/sensors.js @@ -0,0 +1,629 @@ +/* + Copyright (c) 2018, Chris Monahan + + 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. +*/ + +const GObject = imports.gi.GObject; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const FileModule = Me.imports.helpers.file; +const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']); +const _ = Gettext.gettext; +const NM = imports.gi.NM; + +let GTop, hasGTop = true; +try { + GTop = imports.gi.GTop; +} catch (e) { + global.log(e); + hasGTop = false; +} + +var Sensors = GObject.registerClass({ + GTypeName: 'Sensors', +}, class Sensors extends GObject.Object { + _init(settings, sensorIcons) { + this._settings = settings; + this._sensorIcons = sensorIcons; + + this.resetHistory(); + + this._last_processor = { 'core': {}, 'speed': [] }; + + if (hasGTop) { + this.storage = new GTop.glibtop_fsusage(); + this._storageDevice = ''; + this._findStorageDevice(); + + this._lastRead = 0; + this._lastWrite = 0; + } + } + + _refreshIPAddress(callback) { + // check IP address + new FileModule.File('https://corecoding.com/vitals.php').read().then(contents => { + let obj = JSON.parse(contents); + this._returnValue(callback, 'Public IP', obj['IPv4'], 'network', 'string'); + }).catch(err => { }); + } + + _findStorageDevice() { + new FileModule.File('/proc/mounts').read("\n").then(lines => { + for (let line of Object.values(lines)) { + let loadArray = line.trim().split(/\s+/); + if (loadArray[1] == this._settings.get_string('storage-path')) { + this._storageDevice = loadArray[0]; + break; + } + } + }).catch(err => { }); + } + + query(callback, dwell) { + if (!this._hardware_detected) { + // we could set _hardware_detected in discoverHardwareMonitors, but by + // doing it here, we guarantee avoidance of race conditions + this._hardware_detected = true; + this._discoverHardwareMonitors(callback); + } + + for (let sensor in this._sensorIcons) { + if (this._settings.get_boolean('show-' + sensor)) { + if (sensor == 'temperature' || sensor == 'voltage' || sensor == 'fan') { + // for temp, volt, fan, we have a shared handler + this._queryTempVoltFan(callback, sensor); + } else { + // directly call queryFunction below + let method = '_query' + sensor[0].toUpperCase() + sensor.slice(1); + this[method](callback, dwell); + } + } + } + } + + _queryTempVoltFan(callback, type) { + for (let label in this._tempVoltFanSensors[type]) { + let sensor = this._tempVoltFanSensors[type][label]; + + new FileModule.File(sensor['path']).read().then(value => { + this._returnValue(callback, label, value, type, sensor['format']); + }).catch(err => { + this._returnValue(callback, label, 'disabled', type, sensor['format']); + }); + } + } + + _queryMemory(callback) { + // check memory info + new FileModule.File('/proc/meminfo').read().then(lines => { + let total = 0, avail = 0, swapTotal = 0, swapFree = 0; + + let values = lines.match(/MemTotal:(\s+)(\d+) kB/); + if (values) total = values[2]; + + values = lines.match(/MemAvailable:(\s+)(\d+) kB/); + if (values) avail = values[2]; + + values = lines.match(/SwapTotal:(\s+)(\d+) kB/); + if (values) swapTotal = values[2]; + + values = lines.match(/SwapFree:(\s+)(\d+) kB/); + if (values) swapFree = values[2]; + + let used = total - avail + let utilized = used / total; + + this._returnValue(callback, 'Usage', utilized, 'memory', 'percent'); + this._returnValue(callback, 'memory', utilized, 'memory-group', 'percent'); + this._returnValue(callback, 'Physical', total, 'memory', 'memory'); + this._returnValue(callback, 'Available', avail, 'memory', 'memory'); + this._returnValue(callback, 'Allocated', used, 'memory', 'memory'); + this._returnValue(callback, 'Swap', swapTotal - swapFree, 'memory', 'memory'); + }).catch(err => { }); + } + + _queryProcessor(callback, dwell) { + let columns = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq', 'steal', 'guest', 'guest_nice']; + + // check processor usage + new FileModule.File('/proc/stat').read("\n").then(lines => { + let statistics = {}; + + for (let line of Object.values(lines)) { + let reverse_data = line.match(/^(cpu\d*\s)(.+)/); + if (reverse_data) { + let cpu = reverse_data[1].trim(); + + if (!(cpu in statistics)) + statistics[cpu] = {}; + + if (!(cpu in this._last_processor['core'])) + this._last_processor['core'][cpu] = 0; + + let stats = reverse_data[2].trim().split(' ').reverse(); + for (let column of columns) + statistics[cpu][column] = parseInt(stats.pop()); + } + } + + let cores = Object.keys(statistics).length - 1; + + for (let cpu in statistics) { + let total = statistics[cpu]['user'] + statistics[cpu]['nice'] + statistics[cpu]['system']; + + // make sure we have data to report + if (this._last_processor['core'][cpu] > 0) { + let delta = (total - this._last_processor['core'][cpu]) / dwell; + + // /proc/stat provides overall usage for us under the 'cpu' heading + if (cpu == 'cpu') { + delta = delta / cores; + this._returnValue(callback, 'processor', delta / 100, 'processor-group', 'percent'); + this._returnValue(callback, 'Usage', delta / 100, 'processor', 'percent'); + } else { + this._returnValue(callback, _('Core %d').format(cpu.substr(3)), delta / 100, 'processor', 'percent'); + } + } + + this._last_processor['core'][cpu] = total; + } + + // if frequency scaling is enabled, gather cpu-freq values + if (!this._processor_uses_cpu_info) { + for (let core = 0; core <= cores; core++) { + new FileModule.File('/sys/devices/system/cpu/cpu' + core + '/cpufreq/scaling_cur_freq').read().then(value => { + this._last_processor['speed'][core] = parseInt(value); + }).catch(err => { }); + } + } + }).catch(err => { }); + + // if frequency scaling is disabled, use cpuinfo for speed + if (this._processor_uses_cpu_info) { + // grab CPU frequency + new FileModule.File('/proc/cpuinfo').read("\n").then(lines => { + let freqs = []; + for (let line of Object.values(lines)) { + // grab megahertz + let value = line.match(/^cpu MHz(\s+): ([+-]?\d+(\.\d+)?)/); + if (value) freqs.push(parseFloat(value[2])); + } + + let sum = freqs.reduce((a, b) => a + b); + let hertz = (sum / freqs.length) * 1000 * 1000; + this._returnValue(callback, 'Frequency', hertz, 'processor', 'hertz'); + + //let max_hertz = Math.getMaxOfArray(freqs) * 1000 * 1000; + //this._returnValue(callback, 'Boost', max_hertz, 'processor', 'hertz'); + }).catch(err => { }); + // if frequency scaling is enabled, cpu-freq reports + } else if (Object.values(this._last_processor['speed']).length > 0) { + let sum = this._last_processor['speed'].reduce((a, b) => a + b); + let hertz = (sum / this._last_processor['speed'].length) * 1000; + this._returnValue(callback, 'Frequency', hertz, 'processor', 'hertz'); + //let max_hertz = Math.getMaxOfArray(this._last_processor['speed']) * 1000; + //this._returnValue(callback, 'Boost', max_hertz, 'processor', 'hertz'); + } + } + + _querySystem(callback) { + // check load average + new FileModule.File('/proc/sys/fs/file-nr').read("\t").then(loadArray => { + this._returnValue(callback, 'Open Files', loadArray[0], 'system', 'string'); + }).catch(err => { }); + + // check load average + new FileModule.File('/proc/loadavg').read(' ').then(loadArray => { + let proc = loadArray[3].split('/'); + + this._returnValue(callback, 'Load 1m', loadArray[0], 'system', 'load'); + this._returnValue(callback, 'system', loadArray[0], 'system-group', 'load'); + this._returnValue(callback, 'Load 5m', loadArray[1], 'system', 'load'); + this._returnValue(callback, 'Load 15m', loadArray[2], 'system', 'load'); + this._returnValue(callback, 'Threads Active', proc[0], 'system', 'string'); + this._returnValue(callback, 'Threads Total', proc[1], 'system', 'string'); + }).catch(err => { }); + + // check uptime + new FileModule.File('/proc/uptime').read(' ').then(upArray => { + this._returnValue(callback, 'Uptime', upArray[0], 'system', 'duration'); + + let cores = Object.keys(this._last_processor['core']).length - 1; + if (cores > 0) + this._returnValue(callback, 'Process Time', upArray[0] - upArray[1] / cores, 'processor', 'duration'); + }).catch(err => { }); + } + + _queryNetwork(callback, dwell) { + // check network speed + let directions = ['tx', 'rx']; + let netbase = '/sys/class/net/'; + + new FileModule.File(netbase).list().then(interfaces => { + for (let iface of interfaces) { + for (let direction of directions) { + // lo tx and rx are the same + if (iface == 'lo' && direction == 'rx') continue; + + new FileModule.File(netbase + iface + '/statistics/' + direction + '_bytes').read().then(value => { + // issue #217 - don't include 'lo' traffic in Maximum calculations in values.js + // by not using network-rx or network-tx + let name = iface + ((iface == 'lo')?'':' ' + direction); + + let type = 'network' + ((iface=='lo')?'':'-' + direction); + this._returnValue(callback, name, value, type, 'storage'); + }).catch(err => { }); + } + } + }).catch(err => { }); + + // some may not want public ip checking + if (this._settings.get_boolean('include-public-ip')) { + // check the public ip every hour or when waking from sleep + if (this._next_public_ip_check <= 0) { + this._next_public_ip_check = 3600; + + this._refreshIPAddress(callback); + } + + this._next_public_ip_check -= dwell; + } + + // wireless interface statistics + new FileModule.File('/proc/net/wireless').read("\n", true).then(lines => { + for (let line of Object.values(lines)) { + let netArray = line.trim().split(/\s+/); + let quality_pct = netArray[2].substr(0, netArray[2].length-1) / 70; + let signal = netArray[3].substr(0, netArray[3].length-1); + + this._returnValue(callback, 'WiFi Link Quality', quality_pct, 'network', 'percent'); + this._returnValue(callback, 'WiFi Signal Level', signal, 'network', 'string'); + } + }).catch(err => { }); + } + + _queryStorage(callback, dwell) { + // display zfs arc status, if available + new FileModule.File('/proc/spl/kstat/zfs/arcstats').read().then(lines => { + let target = 0, maximum = 0, current = 0; + + let values = lines.match(/c(\s+)(\d+)(\s+)(\d+)/); + if (values) target = values[4]; + + values = lines.match(/c_max(\s+)(\d+)(\s+)(\d+)/); + if (values) maximum = values[4]; + + values = lines.match(/size(\s+)(\d+)(\s+)(\d+)/); + if (values) current = values[4]; + + // ZFS statistics + this._returnValue(callback, 'ARC Target', target, 'storage', 'storage'); + this._returnValue(callback, 'ARC Maximum', maximum, 'storage', 'storage'); + this._returnValue(callback, 'ARC Current', current, 'storage', 'storage'); + }).catch(err => { }); + + // check disk performance stats + new FileModule.File('/proc/diskstats').read("\n").then(lines => { + for (let line of Object.values(lines)) { + let loadArray = line.trim().split(/\s+/); + if ('/dev/' + loadArray[2] == this._storageDevice) { + var read = (loadArray[5] * 512); + var write = (loadArray[9] * 512); + this._returnValue(callback, 'Read total', read, 'storage', 'storage'); + this._returnValue(callback, 'Write total', write, 'storage', 'storage'); + this._returnValue(callback, 'Read rate', (read - this._lastRead) / dwell, 'storage', 'storage'); + this._returnValue(callback, 'Write rate', (write - this._lastWrite) / dwell, 'storage', 'storage'); + this._lastRead = read; + this._lastWrite = write; + break; + } + } + }).catch(err => { }); + + // skip rest of stats if gtop not available + if (!hasGTop) return; + + GTop.glibtop_get_fsusage(this.storage, this._settings.get_string('storage-path')); + + let total = this.storage.blocks * this.storage.block_size; + let avail = this.storage.bavail * this.storage.block_size; + let free = this.storage.bfree * this.storage.block_size; + let used = total - free; + let reserved = (total - avail) - used; + + this._returnValue(callback, 'Total', total, 'storage', 'storage'); + this._returnValue(callback, 'Used', used, 'storage', 'storage'); + this._returnValue(callback, 'Reserved', reserved, 'storage', 'storage'); + this._returnValue(callback, 'Free', avail, 'storage', 'storage'); + this._returnValue(callback, 'storage', avail, 'storage-group', 'storage'); + } + + _queryBattery(callback) { + let battery_slot = this._settings.get_int('battery-slot'); + + // addresses issue #161 + let batt_key = 'BAT'; + if (battery_slot == 3) { + batt_key = 'CMB'; + battery_slot = 0; + } + + let battery_path = '/sys/class/power_supply/' + batt_key + battery_slot + '/'; + + new FileModule.File(battery_path + 'status').read().then(value => { + this._returnValue(callback, 'State', value, 'battery', ''); + }).catch(err => { }); + + new FileModule.File(battery_path + 'cycle_count').read().then(value => { + if (value > 0 || (value == 0 && !this._settings.get_boolean('hide-zeros'))) + this._returnValue(callback, 'Cycles', value, 'battery', ''); + }).catch(err => { }); + + new FileModule.File(battery_path + 'charge_full').read().then(charge_full => { + new FileModule.File(battery_path + 'voltage_min_design').read().then(voltage_min_design => { + this._returnValue(callback, 'Energy (full)', charge_full * voltage_min_design, 'battery', 'watt-hour'); + new FileModule.File(battery_path + 'charge_full_design').read().then(charge_full_design => { + this._returnValue(callback, 'Capacity', (charge_full / charge_full_design), 'battery', 'percent'); + this._returnValue(callback, 'Energy (design)', charge_full_design * voltage_min_design, 'battery', 'watt-hour'); + }).catch(err => { }); + + new FileModule.File(battery_path + 'voltage_now').read().then(voltage_now => { + this._returnValue(callback, 'Voltage', voltage_now / 1000, 'battery', 'in'); + + new FileModule.File(battery_path + 'current_now').read().then(current_now => { + let watt = current_now * voltage_now; + this._returnValue(callback, 'Rate', watt, 'battery', 'watt'); + this._returnValue(callback, 'battery', watt, 'battery-group', 'watt'); + + new FileModule.File(battery_path + 'charge_now').read().then(charge_now => { + let rest_pwr = voltage_min_design * charge_now; + this._returnValue(callback, 'Energy (now)', rest_pwr, 'battery', 'watt-hour'); + + //let time_left_h = rest_pwr / last_pwr; + //this._returnValue(callback, 'time_left_h', time_left_h, 'battery', ''); + + let level = charge_now / charge_full; + this._returnValue(callback, 'Percentage', level, 'battery', 'percent'); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { + new FileModule.File(battery_path + 'energy_full').read().then(energy_full => { + new FileModule.File(battery_path + 'voltage_min_design').read().then(voltage_min_design => { + this._returnValue(callback, 'Energy (full)', energy_full * 1000000, 'battery', 'watt-hour'); + new FileModule.File(battery_path + 'energy_full_design').read().then(energy_full_design => { + this._returnValue(callback, 'Capacity', (energy_full / energy_full_design), 'battery', 'percent'); + this._returnValue(callback, 'Energy (design)', energy_full_design * 1000000, 'battery', 'watt-hour'); + }).catch(err => { }); + + new FileModule.File(battery_path + 'voltage_now').read().then(voltage_now => { + this._returnValue(callback, 'Voltage', voltage_now / 1000, 'battery', 'in'); + + new FileModule.File(battery_path + 'power_now').read().then(power_now => { + this._returnValue(callback, 'Rate', power_now * 1000000, 'battery', 'watt'); + this._returnValue(callback, 'battery', power_now * 1000000, 'battery-group', 'watt'); + + new FileModule.File(battery_path + 'energy_now').read().then(energy_now => { + this._returnValue(callback, 'Energy (now)', energy_now * 1000000, 'battery', 'watt-hour'); + + //let time_left_h = energy_now / last_pwr; + //this._returnValue(callback, 'time_left_h', time_left_h, 'battery', ''); + + let level = energy_now / energy_full; + this._returnValue(callback, 'Percentage', level, 'battery', 'percent'); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { }); + }).catch(err => { }); + }); + } + + _returnValue(callback, label, value, type, format) { + callback(label, value, type, format); + } + + _discoverHardwareMonitors(callback) { + this._tempVoltFanSensors = { 'temperature': {}, 'voltage': {}, 'fan': {} }; + + let hwbase = '/sys/class/hwmon/'; + + // process sensor_types now so it is not called multiple times below + let sensor_types = {}; + + if (this._settings.get_boolean('show-temperature')) + sensor_types['temp'] = 'temperature'; + + if (this._settings.get_boolean('show-voltage')) + sensor_types['in'] = 'voltage'; + + if (this._settings.get_boolean('show-fan')) + sensor_types['fan'] = 'fan'; + + // a little informal, but this code has zero I/O block + new FileModule.File(hwbase).list().then(files => { + for (let file of files) { + // grab name of sensor + new FileModule.File(hwbase + file + '/name').read().then(name => { + // are we dealing with a CPU? + if (name == 'coretemp') { + // determine which processor (socket) we are dealing with + new FileModule.File(hwbase + file + '/temp1_label').read().then(prefix => { + this._processTempVoltFan(callback, sensor_types, prefix, hwbase + file, file); + }).catch(err => { + // this shouldn't be necessary, but just in case temp1_label doesn't exist + // attempt to fix #266 + this._processTempVoltFan(callback, sensor_types, name, hwbase + file, file); + }); + } else { + // not a CPU, process all other sensors + this._processTempVoltFan(callback, sensor_types, name, hwbase + file, file); + } + }).catch(err => { + new FileModule.File(hwbase + file + '/device/name').read().then(name => { + this._processTempVoltFan(callback, sensor_types, name, hwbase + file + '/device', file); + }).catch(err => { }); + }); + } + }).catch(err => { }); + + // does this system support cpu scaling? if so we will use it to grab Frequency and Boost below + new FileModule.File('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq').read().then(value => { + this._processor_uses_cpu_info = false; + }).catch(err => { }); + + // grab static CPU information + new FileModule.File('/proc/cpuinfo').read("\n").then(lines => { + let vendor_id = ''; + let bogomips = ''; + let sockets = {}; + let cache = ''; + + for (let line of Object.values(lines)) { + // grab cpu vendor + let value = line.match(/^vendor_id(\s+): (\w+.*)/); + if (value) vendor_id = value[2]; + + // grab bogomips + value = line.match(/^bogomips(\s+): (\d*\.?\d*)$/); + if (value) bogomips = value[2]; + + // grab processor count + value = line.match(/^physical id(\s+): (\d+)$/); + if (value) sockets[value[2]] = 1; + + // grab cache + value = line.match(/^cache size(\s+): (\d+) KB$/); + if (value) cache = value[2]; + } + + this._returnValue(callback, 'Vendor', vendor_id, 'processor', 'string'); + this._returnValue(callback, 'Bogomips', bogomips, 'processor', 'string'); + this._returnValue(callback, 'Sockets', Object.keys(sockets).length, 'processor', 'string'); + this._returnValue(callback, 'Cache', cache, 'processor', 'memory'); + }).catch(err => { }); + } + + _processTempVoltFan(callback, sensor_types, name, path, file) { + let sensor_files = [ 'input', 'label' ]; + + // grab files from directory + new FileModule.File(path).list().then(files2 => { + let trisensors = {}; + + // loop over files from directory + for (let file2 of Object.values(files2)) { + // simple way of processing input and label (from above) + for (let key of Object.values(sensor_files)) { + // process toggled on sensors from extension preferences + for (let sensor_type in sensor_types) { + if (file2.substr(0, sensor_type.length) == sensor_type && file2.substr(-(key.length+1)) == '_' + key) { + let key2 = file + file2.substr(0, file2.indexOf('_')); + + if (!(key2 in trisensors)) { + trisensors[key2] = { + 'type': sensor_types[sensor_type], + 'format': sensor_type, + 'label': path + '/name' + }; + } + + trisensors[key2][key] = path + '/' + file2; + } + } + } + } + + for (let obj of Object.values(trisensors)) { + if (!('input' in obj)) + continue; + + new FileModule.File(obj['input']).read().then(value => { + let extra = (obj['label'].indexOf('_label')==-1) ? ' ' + obj['input'].substr(obj['input'].lastIndexOf('/')+1).split('_')[0] : ''; + + if (value > 0 || !this._settings.get_boolean('hide-zeros') || obj['type'] == 'fan') { + new FileModule.File(obj['label']).read().then(label => { + this._addTempVoltFan(callback, obj, name, label, extra, value); + }).catch(err => { + let tmpFile = obj['label'].substr(0, obj['label'].lastIndexOf('/')) + '/name'; + new FileModule.File(tmpFile).read().then(label => { + this._addTempVoltFan(callback, obj, name, label, extra, value); + }).catch(err => { }); + }); + } + }).catch(err => { }); + } + }).catch(err => { }); + } + + _addTempVoltFan(callback, obj, name, label, extra, value) { + // prepend module that provided sensor data + if (name != label) label = name + ' ' + label; + + //if (label == 'nvme Composite') label = 'NVMe'; + //if (label == 'nouveau') label = 'Nvidia'; + + label = label + extra; + + // in the future we will read /etc/sensors3.conf + if (label == 'acpitz temp1') label = 'ACPI Thermal Zone'; + if (label == 'pch_cannonlake temp1') label = 'Platform Controller Hub'; + if (label == 'iwlwifi_1 temp1') label = 'Wireless Adapter'; + if (label == 'Package id 0') label = 'Processor 0'; + if (label == 'Package id 1') label = 'Processor 1'; + label = label.replace('Package id', 'CPU'); + + let types = [ 'temperature', 'voltage', 'fan' ]; + for (let type of types) { + // check if this label already exists + if (label in this._tempVoltFanSensors[type]) { + for (let i = 2; i <= 9; i++) { + // append an incremented number to end + let new_label = label + ' ' + i; + + // if new label is available, use it + if (!(new_label in this._tempVoltFanSensors[type])) { + label = new_label; + break; + } + } + } + } + + // update screen on initial build to prevent delay on update + this._returnValue(callback, label, value, obj['type'], obj['format']); + + this._tempVoltFanSensors[obj['type']][label] = { + 'format': obj['format'], + 'path': obj['input'] + }; + } + + resetHistory() { + this._next_public_ip_check = 0; + this._hardware_detected = false; + this._processor_uses_cpu_info = true; + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/stylesheet.css new file mode 100644 index 0000000..adec425 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/stylesheet.css @@ -0,0 +1,16 @@ +.vitals-icon { icon-size: 16px; } +.vitals-menu-button-container {} +.vitals-panel-icon-temperature { margin: 0 1px 0 8px; padding: 0; } +.vitals-panel-icon-voltage { margin: 0 0 0 8px; padding: 0; } +.vitals-panel-icon-fan { margin: 0 4px 0 8px; padding: 0; } +.vitals-panel-icon-memory { margin: 0 2px 0 8px; padding: 0; } +.vitals-panel-icon-processor { margin: 0 3px 0 8px; padding: 0; } +.vitals-panel-icon-system { margin: 0 3px 0 8px; padding: 0; } +.vitals-panel-icon-network { margin: 0 3px 0 8px; padding: 0; } +.vitals-panel-icon-storage { margin: 0 2px 0 8px; padding: 0; } +.vitals-panel-icon-battery { margin: 0 4px 0 8px; padding: 0; } +.vitals-panel-label { margin: 0 3px 0 0; padding: 0; } +.vitals-button-action { -st-icon-style: symbolic; border-radius: 32px; margin: 0px; min-height: 22px; min-width: 22px; padding: 10px; font-size: 100%; border: 1px solid transparent; } +.vitals-button-action:hover, .vitals-button-action:focus { border-color: #777; } +.vitals-button-action > StIcon { icon-size: 16px; } +.vitals-button-box { padding: 0px; spacing: 22px; } diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/values.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/values.js new file mode 100644 index 0000000..b3e72d9 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/Vitals@CoreCoding.com/values.js @@ -0,0 +1,337 @@ +/* + Copyright (c) 2018, Chris Monahan + + 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. +*/ + +const GObject = imports.gi.GObject; +const Me = imports.misc.extensionUtils.getCurrentExtension(); + +const cbFun = (d, c) => { + let bb = d[1] % c[0], + aa = (d[1] - bb) / c[0]; + aa = aa > 0 ? aa + c[1] : ''; + + return [d[0] + aa, bb]; +}; + +var Values = GObject.registerClass({ + GTypeName: 'Values', +}, class Values extends GObject.Object { + + _init(settings, sensorIcons) { + this._settings = settings; + this._sensorIcons = sensorIcons; + + this._networkSpeedOffset = {}; + this._networkSpeeds = {}; + + this._history = {}; + //this._history2 = {}; + this.resetHistory(); + } + + _legible(value, sensorClass) { + let unit = 1000; + if (value === null) return 'N/A'; + let use_higher_precision = this._settings.get_boolean('use-higher-precision'); + let memory_measurement = this._settings.get_int('memory-measurement') + let storage_measurement = this._settings.get_int('storage-measurement') + let use_bps = (this._settings.get_int('network-speed-format') == 1); + + let format = ''; + let ending = ''; + let exp = 0; + + var decimal = [ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ]; + var binary = [ 'B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB' ]; + var hertz = [ 'Hz', 'KHz', 'MHz', 'GHz', 'THz', 'PHz', 'EHz', 'ZHz' ]; + + switch (sensorClass) { + case 'percent': + format = (use_higher_precision)?'%.1f%s':'%d%s'; + value = value * 100; + if (value > 100) value = 100; + ending = '%'; + break; + case 'temp': + value = value / 1000; + ending = '°C'; + + // are we converting to fahrenheit? + if (this._settings.get_int('unit') == 1) { + value = ((9 / 5) * value + 32); + ending = '°F'; + } + + format = (use_higher_precision)?'%.1f%s':'%d%s'; + break; + case 'fan': + format = '%d %s'; + ending = 'RPM'; + break; + case 'in': // voltage + value = value / 1000; + format = ((value >= 0) ? '+' : '-') + ((use_higher_precision)?'%.2f %s':'%.1f %s'); + ending = 'V'; + break; + case 'hertz': + if (value > 0) { + exp = Math.floor(Math.log(value) / Math.log(unit)); + if (value >= Math.pow(unit, exp) * (unit - 0.05)) exp++; + value = parseFloat((value / Math.pow(unit, exp))); + } + + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + ending = hertz[exp]; + break; + case 'memory': + unit = (memory_measurement)?1000:1024; + + if (value > 0) { + value *= unit; + exp = Math.floor(Math.log(value) / Math.log(unit)); + if (value >= Math.pow(unit, exp) * (unit - 0.05)) exp++; + value = parseFloat((value / Math.pow(unit, exp))); + } + + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + + if (memory_measurement) + ending = decimal[exp]; + else + ending = binary[exp]; + + break; + case 'storage': + unit = (storage_measurement)?1000:1024; + + if (value > 0) { + exp = Math.floor(Math.log(value) / Math.log(unit)); + if (value >= Math.pow(unit, exp) * (unit - 0.05)) exp++; + value = parseFloat((value / Math.pow(unit, exp))); + } + + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + + if (storage_measurement) + ending = decimal[exp]; + else + ending = binary[exp]; + + break; + case 'speed': + if (value > 0) { + if (use_bps) value *= 8; + exp = Math.floor(Math.log(value) / Math.log(unit)); + if (value >= Math.pow(unit, exp) * (unit - 0.05)) exp++; + value = parseFloat((value / Math.pow(unit, exp))); + } + + format = (use_higher_precision)?'%.1f %s':'%.0f %s'; + + if (use_bps) { + ending = decimal[exp].replace('B', 'bps'); + } else { + ending = decimal[exp] + '/s'; + } + + break; + case 'duration': + let scale = [24, 60, 60]; + let units = ['d ', 'h ', 'm ']; + + // show seconds on higher precision or if value under a minute + if (use_higher_precision || value < 60) { + scale.push(1); + units.push('s '); + } + + let rslt = scale.map((d, i, a) => a.slice(i).reduce((d, c) => d * c)) + .map((d, i) => ([d, units[i]])) + .reduce(cbFun, ['', value]); + + value = rslt[0].trim(); + + format = '%s'; + break; + case 'milliamp': + format = (use_higher_precision)?'%.1f %s':'%d %s'; + value = value / 1000; + ending = 'mA'; + break; + case 'milliamp-hour': + format = (use_higher_precision)?'%.1f %s':'%d %s'; + value = value / 1000; + ending = 'mAh'; + break; + case 'watt': + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + value = value / 1000000000000; + ending = 'W'; + break; + case 'watt-hour': + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + value = value / 1000000000000; + ending = 'Wh'; + break; + case 'load': + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + break; + default: + format = '%s'; + break; + } + + return format.format(value, ending); + } + + returnIfDifferent(dwell, label, value, type, format, key) { + let output = []; + + // make sure the keys exist + if (!(type in this._history)) this._history[type] = {}; + + // no sense in continuing when the raw value has not changed + if (type != 'network-rx' && type != 'network-tx' && + key in this._history[type] && this._history[type][key][1] == value) + return output; + + // is the value different from last time? + let legible = this._legible(value, format); + + // don't return early when dealing with network traffic + if (type != 'network-rx' && type != 'network-tx') { + // only update when we are coming through for the first time, or if a value has changed + if (key in this._history[type] && this._history[type][key][0] == legible) + return output; + + // add label as it was sent from sensors class + output.push([label, legible, type, key]); + } + + // save previous values to update screen on chnages only + let previousValue = this._history[type][key]; + this._history[type][key] = [legible, value]; + + // process average, min and max values + if (type == 'temperature' || type == 'voltage' || type == 'fan') { + let vals = Object.values(this._history[type]).map(x => parseFloat(x[1])); + + // show value in group even if there is one value present + let sum = vals.reduce((a, b) => a + b); + let avg = this._legible(sum / vals.length, format); + output.push([type, avg, type + '-group', '']); + + // If only one value is present, don't display avg, min and max + if (vals.length > 1) { + output.push(['Average', avg, type, '__' + type + '_avg__']); + + // calculate Minimum value + let min = Math.min(...vals); + min = this._legible(min, format); + output.push(['Minimum', min, type, '__' + type + '_min__']); + + // calculate Maximum value + let max = Math.max(...vals); + max = this._legible(max, format); + output.push(['Maximum', max, type, '__' + type + '_max__']); + } + } else if (type == 'network-rx' || type == 'network-tx') { + let direction = type.split('-')[1]; + + // appends total upload and download for all interfaces for #216 + let vals = Object.values(this._history[type]).map(x => parseFloat(x[1])); + let sum = vals.reduce((partialSum, a) => partialSum + a, 0); + output.push(['Boot ' + direction, this._legible(sum, format), type, '__' + type + '_boot__']); + + // keeps track of session start point + if (!(key in this._networkSpeedOffset) || this._networkSpeedOffset[key] <= 0) + this._networkSpeedOffset[key] = sum; + + // outputs session upload and download for all interfaces for #234 + output.push(['Session ' + direction, this._legible(sum - this._networkSpeedOffset[key], format), type, '__' + type + '_ses__']); + + // calculate speed for this interface + let speed = (value - previousValue[1]) / dwell; + output.push([label, this._legible(speed, 'speed'), type, key]); + + // store speed for Device report + if (!(direction in this._networkSpeeds)) this._networkSpeeds[direction] = {}; + if (!(label in this._networkSpeeds[direction])) this._networkSpeeds[direction][label] = 0; + + // store value for next go around + if (value > 0 || (value == 0 && !this._settings.get_boolean('hide-zeros'))) + this._networkSpeeds[direction][label] = speed; + + // calculate total upload and download device speed + for (let direction in this._networkSpeeds) { + let sum = 0; + for (let iface in this._networkSpeeds[direction]) + sum += parseFloat(this._networkSpeeds[direction][iface]); + + sum = this._legible(sum, 'speed'); + output.push(['Device ' + direction, sum, 'network-' + direction, '__network-' + direction + '_max__']); + // append download speed to group itself + if (direction == 'rx') output.push([type, sum, type + '-group', '']); + } + } + +/* + global.log('before', JSON.stringify(output)); + for (let i = output.length - 1; i >= 0; i--) { + let sensor = output[i]; + // sensor[0]=label, sensor[1]=value, sensor[2]=type, sensor[3]=key) + + //["CPU Core 5","46°C","temperature","_temperature_hwmon8temp7_"] + + // make sure the keys exist + if (!(sensor[2] in this._history2)) this._history2[sensor[2]] = {}; + + if (sensor[3] in this._history2[sensor[2]]) { + if (this._history2[sensor[2]][sensor[3]] == sensor[1]) { + output.splice(i, 1); + } + } + + this._history2[sensor[2]][sensor[3]] = sensor[1]; + } + + global.log(' after', JSON.stringify(output)); + global.log('***************************'); +*/ + + return output; + } + + resetHistory() { + // 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) { + this._history[sensor] = {}; + this._history[sensor + '-group'] = {}; + //this._history2[sensor] = {}; + //this._history2[sensor + '-group'] = {}; + } + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/appfolders.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/appfolders.js new file mode 100644 index 0000000..b69f49e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/appfolders.js @@ -0,0 +1,265 @@ +'use strict'; + +const { Shell, GLib, Clutter } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { PaintSignals } = Me.imports.effects.paint_signals; +const Tweener = imports.tweener.tweener; + +const transparent = Clutter.Color.from_pixel(0x00000000); +const FOLDER_DIALOG_ANIMATION_TIME = 200; +const FRAME_UPDATE_PERIOD = 16; + +const DIALOGS_STYLES = [ + "", + "appfolder-dialogs-transparent", + "appfolder-dialogs-light", + "appfolder-dialogs-dark" +]; + +let original_zoomAndFadeIn = null; +let original_zoomAndFadeOut = null; +let sigma; +let brightness; + +let _zoomAndFadeIn = function () { + let [sourceX, sourceY] = + this._source.get_transformed_position(); + let [dialogX, dialogY] = + this.child.get_transformed_position(); + + this.child.set({ + translation_x: sourceX - dialogX, + translation_y: sourceY - dialogY, + scale_x: this._source.width / this.child.width, + scale_y: this._source.height / this.child.height, + opacity: 0, + }); + + this.set_background_color(transparent); + + let blur_effect = this.get_effect("appfolder-blur"); + + blur_effect.sigma = 0; + blur_effect.brightness = 1.0; + Tweener.addTween(blur_effect, + { + sigma: sigma, + brightness: brightness, + time: FOLDER_DIALOG_ANIMATION_TIME / 1000, + transition: 'easeOutQuad' + } + ); + + this.child.ease({ + translation_x: 0, + translation_y: 0, + scale_x: 1, + scale_y: 1, + opacity: 255, + duration: FOLDER_DIALOG_ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + }); + + this._needsZoomAndFade = false; + + if (this._sourceMappedId === 0) { + this._sourceMappedId = this._source.connect( + 'notify::mapped', this._zoomAndFadeOut.bind(this)); + } +}; + +let _zoomAndFadeOut = function () { + if (!this._isOpen) + return; + + if (!this._source.mapped) { + this.hide(); + return; + } + + let [sourceX, sourceY] = + this._source.get_transformed_position(); + let [dialogX, dialogY] = + this.child.get_transformed_position(); + + this.set_background_color(transparent); + + let blur_effect = this.get_effect("appfolder-blur"); + Tweener.addTween(blur_effect, + { + sigma: 0, + brightness: 1.0, + time: FOLDER_DIALOG_ANIMATION_TIME / 1000, + transition: 'easeInQuad' + } + ); + + this.child.ease({ + translation_x: sourceX - dialogX, + translation_y: sourceY - dialogY, + scale_x: this._source.width / this.child.width, + scale_y: this._source.height / this.child.height, + opacity: 0, + duration: FOLDER_DIALOG_ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => { + this.child.set({ + translation_x: 0, + translation_y: 0, + scale_x: 1, + scale_y: 1, + opacity: 255, + }); + this.hide(); + + this._popdownCallbacks.forEach(func => func()); + this._popdownCallbacks = []; + }, + }); + + this._needsZoomAndFade = false; +}; + + +var AppFoldersBlur = class AppFoldersBlur { + constructor(connections, prefs) { + this.connections = connections; + this.paint_signals = new PaintSignals(connections); + this.prefs = prefs; + } + + enable() { + this._log("blurring appfolders"); + + brightness = this.prefs.appfolder.CUSTOMIZE + ? this.prefs.appfolder.BRIGHTNESS + : this.prefs.BRIGHTNESS; + sigma = this.prefs.appfolder.CUSTOMIZE + ? this.prefs.appfolder.SIGMA + : this.prefs.SIGMA; + + let appDisplay = Main.overview._overview.controls._appDisplay; + + if (appDisplay._folderIcons.length > 0) { + this.blur_appfolders(); + } + + this.connections.connect( + appDisplay, 'view-loaded', this.blur_appfolders.bind(this) + ); + } + + blur_appfolders() { + let appDisplay = Main.overview._overview.controls._appDisplay; + + if (this.prefs.HACKS_LEVEL === 1 || this.prefs.HACKS_LEVEL === 2) + this._log(`appfolders hack level ${this.prefs.HACKS_LEVEL}`); + + appDisplay._folderIcons.forEach(icon => { + icon._ensureFolderDialog(); + + if (original_zoomAndFadeIn == null) { + original_zoomAndFadeIn = icon._dialog._zoomAndFadeIn; + } + if (original_zoomAndFadeOut == null) { + original_zoomAndFadeOut = icon._dialog._zoomAndFadeOut; + } + + let blur_effect = new Shell.BlurEffect({ + name: "appfolder-blur", + sigma: sigma, + brightness: brightness, + mode: Shell.BlurMode.BACKGROUND + }); + + icon._dialog.remove_effect_by_name("appfolder-blur"); + icon._dialog.add_effect(blur_effect); + + DIALOGS_STYLES.forEach( + style => icon._dialog._viewBox.remove_style_class_name(style) + ); + + icon._dialog._viewBox.add_style_class_name( + DIALOGS_STYLES[this.prefs.appfolder.STYLE_DIALOGS] + ); + + // finally override the builtin functions + + icon._dialog._zoomAndFadeIn = _zoomAndFadeIn; + icon._dialog._zoomAndFadeOut = _zoomAndFadeOut; + + + // 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.prefs.HACKS_LEVEL === 1 || this.prefs.HACKS_LEVEL === 2) { + this.paint_signals.disconnect_all_for_actor(icon._dialog); + this.paint_signals.connect(icon._dialog, blur_effect); + } else { + this.paint_signals.disconnect_all(); + } + }); + }; + + set_sigma(s) { + sigma = s; + if (this.prefs.appfolder.BLUR) + this.blur_appfolders(); + } + + set_brightness(b) { + brightness = b; + if (this.prefs.appfolder.BLUR) + this.blur_appfolders(); + } + + // not implemented for dynamic blur + set_color(c) { } + set_noise_amount(n) { } + set_noise_lightness(l) { } + + disable() { + this._log("removing blur from appfolders"); + + let appDisplay = Main.overview._overview.controls._appDisplay; + + if (original_zoomAndFadeIn != null) { + appDisplay._folderIcons.forEach(icon => { + if (icon._dialog) + icon._dialog._zoomAndFadeIn = original_zoomAndFadeIn; + }); + } + + if (original_zoomAndFadeOut != null) { + appDisplay._folderIcons.forEach(icon => { + if (icon._dialog) + icon._dialog._zoomAndFadeOut = original_zoomAndFadeOut; + }); + } + + appDisplay._folderIcons.forEach(icon => { + if (icon._dialog) { + icon._dialog.remove_effect_by_name("appfolder-blur"); + DIALOGS_STYLES.forEach( + s => icon._dialog._viewBox.remove_style_class_name(s) + ); + } + }); + + this.connections.disconnect_all(); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > appfolders] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/applications.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/applications.js new file mode 100644 index 0000000..c040451 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/applications.js @@ -0,0 +1,541 @@ +'use strict'; + +const { Shell, Clutter, Meta, GLib } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { PaintSignals } = Me.imports.effects.paint_signals; +const { ApplicationsService } = Me.imports.dbus.services; + +var ApplicationsBlur = class ApplicationsBlur { + constructor(connections, prefs) { + this.connections = connections; + this.prefs = prefs; + this.paint_signals = new PaintSignals(connections); + + // stores every blurred window + this.window_map = new Map(); + // stores every blur actor + this.blur_actor_map = new Map(); + } + + enable() { + this._log("blurring applications..."); + + // export dbus service for preferences + this.service = new ApplicationsService; + this.service.export(); + + // blur already existing windows + this.update_all_windows(); + + // blur every new window + this.connections.connect( + global.display, + 'window-created', + (_meta_display, meta_window) => { + this._log("window created"); + + if (meta_window) { + let window_actor = meta_window.get_compositor_private(); + this.track_new(window_actor, meta_window); + } + } + ); + + this.connect_to_overview(); + } + + /// Connect to the overview being opened/closed to force the blur being + /// shown on every window of the workspaces viewer. + connect_to_overview() { + this.connections.disconnect_all_for(Main.overview); + + if (this.prefs.applications.BLUR_ON_OVERVIEW) { + // when the overview is opened, show every window actors (which + // allows the blur to be shown too) + this.connections.connect( + Main.overview, 'showing', + _ => this.window_map.forEach((meta_window, _pid) => { + let window_actor = meta_window.get_compositor_private(); + window_actor.show(); + }) + ); + + // when the overview is closed, hide every actor that is not on the + // current workspace (to mimic the original behaviour) + 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 + ) + window_actor.hide(); + }); + } + ); + } + } + + /// Iterate through all existing windows and add blur as needed. + update_all_windows() { + // remove all previously blurred windows, in the case where the + // whitelist was changed + this.window_map.forEach(((_meta_window, pid) => { + this.remove_blur(pid); + })); + + for ( + let i = 0; + i < global.workspace_manager.get_n_workspaces(); + ++i + ) { + let workspace = global.workspace_manager.get_workspace_by_index(i); + let windows = workspace.list_windows(); + + windows.forEach(meta_window => { + let window_actor = meta_window.get_compositor_private(); + + // disconnect previous signals + this.connections.disconnect_all_for(window_actor); + + this.track_new(window_actor, meta_window); + }); + } + } + + /// Adds the needed signals to every new tracked window, and adds blur if + /// needed. + track_new(window_actor, meta_window) { + let pid = ("" + Math.random()).slice(2, 16); + + window_actor['blur_provider_pid'] = pid; + meta_window['blur_provider_pid'] = pid; + + // remove the blur when the window is destroyed + this.connections.connect(window_actor, 'destroy', window_actor => { + let pid = window_actor.blur_provider_pid; + if (this.blur_actor_map.has(pid)) { + this.remove_blur(pid); + } + this.window_map.delete(pid); + }); + + // update the blur when mutter-hint or wm-class is changed + for (const prop of ['mutter-hints', 'wm-class']) { + this.connections.connect( + meta_window, + `notify::${prop}`, + _ => { + let pid = meta_window.blur_provider_pid; + this._log(`${prop} changed for pid ${pid}`); + + let window_actor = meta_window.get_compositor_private(); + this.check_blur(pid, window_actor, meta_window); + } + ); + } + + // update the position and size when the window size changes + this.connections.connect(meta_window, 'size-changed', () => { + if (this.blur_actor_map.has(pid)) { + let allocation = this.compute_allocation(meta_window); + let blur_actor = this.blur_actor_map.get(pid); + blur_actor.x = allocation.x; + blur_actor.y = allocation.y; + blur_actor.width = allocation.width; + blur_actor.height = allocation.height; + } + }); + + this.check_blur(pid, window_actor, meta_window); + } + + /// Checks if the given actor needs to be blurred. + /// + /// In order to be blurred, a window either: + /// - is whitelisted in the user preferences if not enable-all + /// - is not blacklisted if enable-all + /// - has a correct mutter hint, set to `blur-provider=sigma_value` + check_blur(pid, window_actor, meta_window) { + let mutter_hint = meta_window.get_mutter_hints(); + let window_wm_class = meta_window.get_wm_class(); + + let enable_all = this.prefs.applications.ENABLE_ALL; + let whitelist = this.prefs.applications.WHITELIST; + let blacklist = this.prefs.applications.BLACKLIST; + + this._log(`checking blur for ${pid}`); + + // either the window is included in whitelist + if (window_wm_class !== "" + && ((enable_all && !blacklist.includes(window_wm_class)) + || (!enable_all && whitelist.includes(window_wm_class)) + ) + && [ + Meta.FrameType.NORMAL, + Meta.FrameType.DIALOG, + Meta.FrameType.MODAL_DIALOG + ].includes(meta_window.get_frame_type()) + ) { + this._log(`application ${pid} listed, blurring it`); + + // get blur effect parameters + + let brightness, sigma; + + if (this.prefs.applications.CUSTOMIZE) { + brightness = this.prefs.applications.BRIGHTNESS; + sigma = this.prefs.applications.SIGMA; + } else { + brightness = this.prefs.BRIGHTNESS; + sigma = this.prefs.SIGMA; + } + + this.update_blur(pid, window_actor, meta_window, brightness, sigma); + } + + // or blur is asked by window itself + else if ( + mutter_hint != null && + mutter_hint.includes("blur-provider") + ) { + this._log(`application ${pid} has hint ${mutter_hint}, parsing`); + + // get blur effect parameters + let [brightness, sigma] = this.parse_xprop(mutter_hint); + + this.update_blur(pid, window_actor, meta_window, brightness, sigma); + } + + // remove blur if the mutter hint is no longer valid, and the window + // is not explicitly whitelisted or un-blacklisted + else if (this.blur_actor_map.has(pid)) { + this.remove_blur(pid); + } + } + + /// When given the xprop property, returns the brightness and sigma values + /// matching. If one of the two values is invalid, or missing, then it uses + /// default values. + /// + /// An xprop property is valid if it is in one of the following formats: + /// + /// blur-provider=sigma:60,brightness:0.9 + /// blur-provider=s:10,brightness:0.492 + /// blur-provider=b:1.0,s:16 + /// + /// Brightness is a floating-point between 0.0 and 1.0 included. + /// Sigma is an integer between 0 and 999 included. + /// + /// If sigma is set to 0, then the blur is removed. + /// Setting "default" instead of the two values will make the + /// extension use its default value. + /// + /// Note that no space can be inserted. + /// + parse_xprop(property) { + // set brightness and sigma to default values + let brightness, sigma; + if (this.prefs.applications.CUSTOMIZE) { + brightness = this.prefs.applications.BRIGHTNESS; + sigma = this.prefs.applications.SIGMA; + } else { + brightness = this.prefs.BRIGHTNESS; + sigma = this.prefs.SIGMA; + } + + // get the argument of the property + let arg = property.match("blur-provider=(.*)"); + this._log(`argument = ${arg}`); + + // if argument is valid, parse it + if (arg != null) { + // verify if there is only one value: in this case, this is sigma + let maybe_sigma = parseInt(arg[1]); + + if ( + !isNaN(maybe_sigma) && + maybe_sigma >= 0 && + maybe_sigma <= 999 + ) { + sigma = maybe_sigma; + } else { + // perform pattern matching + let res_b = arg[1].match("(brightness|b):(default|0?1?\.[0-9]*)"); + let res_s = arg[1].match("(sigma|s):(default|\\d{1,3})"); + + // if values are valid and not default, change them to the xprop one + if ( + res_b != null && res_b[2] !== 'default' + ) { + brightness = parseFloat(res_b[2]); + } + + if ( + res_s != null && res_s[2] !== 'default' + ) { + sigma = parseInt(res_s[2]); + } + } + } + + this._log(`brightness = ${brightness}, sigma = ${sigma}`); + + return [brightness, sigma]; + } + + /// Updates the blur on a window which needs to be blurred. + update_blur(pid, window_actor, meta_window, brightness, sigma) { + // the window is already blurred, update its blur effect + if (this.blur_actor_map.has(pid)) { + // window is already blurred, but sigma is null: remove the blur + if (sigma === 0) { + this.remove_blur(pid); + } + // window is already blurred and sigma is non-null: update it + else { + this.update_blur_effect( + this.blur_actor_map.get(pid), + brightness, + sigma + ); + } + } + + // the window is not blurred, and sigma is a non-null value: blur it + else if (sigma !== 0) { + // window is not blurred, blur it + this.create_blur_effect( + pid, + window_actor, + meta_window, + brightness, + sigma + ); + } + } + + /// 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, + brightness: brightness, + mode: Shell.BlurMode.BACKGROUND + }); + + let blur_actor = this.create_blur_actor( + meta_window, + window_actor, + blur_effect + ); + + // if hacks are selected, force to repaint the window + if (this.prefs.HACKS_LEVEL === 1 || this.prefs.HACKS_LEVEL === 2) { + this._log("applications hack level 1 or 2"); + + this.paint_signals.disconnect_all(); + this.paint_signals.connect(blur_actor, blur_effect); + } else { + this.paint_signals.disconnect_all(); + } + + // insert the blurred widget + window_actor.insert_child_at_index(blur_actor, 0); + + // make sure window is blurred in overview + if (this.prefs.applications.BLUR_ON_OVERVIEW) + this.enforce_window_visibility_on_overview_for(window_actor); + + // set the window actor's opacity + this.set_window_opacity(window_actor, this.prefs.applications.OPACITY); + + // register the blur actor/effect + blur_actor['blur_provider_pid'] = pid; + this.blur_actor_map.set(pid, blur_actor); + this.window_map.set(pid, meta_window); + + // hide the blur if window is invisible + if (!window_actor.visible) { + blur_actor.hide(); + } + + // hide the blur if window becomes invisible + this.connections.connect( + window_actor, + 'notify::visible', + window_actor => { + let pid = window_actor.blur_provider_pid; + if (window_actor.visible) { + this.blur_actor_map.get(pid).show(); + } else { + this.blur_actor_map.get(pid).hide(); + } + } + ); + } + + /// Makes sure that, when the overview is visible, the window actor will + /// stay visible no matter what. + /// We can instead hide the last child of the window actor, which will + /// improve performances without hiding the blur effect. + enforce_window_visibility_on_overview_for(window_actor) { + this.connections.connect(window_actor, 'notify::visible', + _ => { + if (this.prefs.applications.BLUR_ON_OVERVIEW) { + if ( + !window_actor.visible + && Main.overview.visible + ) { + window_actor.show(); + window_actor.get_last_child().hide(); + } + else if ( + window_actor.visible + ) + window_actor.get_last_child().show(); + } + } + ); + } + + /// Set the opacity of the window actor that sits on top of the blur effect. + set_window_opacity(window_actor, opacity) { + window_actor.get_children().forEach(child => { + if (child.name !== "blur-actor") + child.opacity = opacity; + }); + } + + /// 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. + compute_allocation(meta_window) { + const is_wayland = Meta.is_wayland_compositor(); + const monitor_index = meta_window.get_monitor(); + const scale = is_wayland + ? Main.layoutManager.monitors[monitor_index].geometry_scale + : 1; + + let frame = meta_window.get_frame_rect(); + let buffer = meta_window.get_buffer_rect(); + + return { + x: (frame.x - buffer.x) / scale, + y: (frame.y - buffer.y) / scale, + width: frame.width / scale, + height: frame.height / scale + }; + } + + /// Returns a new already blurred widget, configured to follow the size and + /// position of its target window. + create_blur_actor(meta_window, window_actor, blur_effect) { + // compute the size and position + let allocation = this.compute_allocation(meta_window); + + // create the actor + let blur_actor = new Clutter.Actor({ + x: allocation.x, + y: allocation.y, + width: allocation.width, + height: allocation.height + }); + + // add the effect + blur_actor.add_effect_with_name('blur-effect', blur_effect); + + return blur_actor; + } + + /// 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.brightness = brightness; + } + + /// Removes the blur actor from the shell and unregister it. + remove_blur(pid) { + this._log(`removing blur for pid ${pid}`); + + let meta_window = this.window_map.get(pid); + // disconnect needed signals and untrack window + if (meta_window) { + this.window_map.delete(pid); + let window_actor = meta_window.get_compositor_private(); + + let blur_actor = this.blur_actor_map.get(pid); + if (blur_actor) { + this.blur_actor_map.delete(pid); + + if (window_actor) { + // reset the opacity + this.set_window_opacity(window_actor, 255); + + // remove the blurred actor + window_actor.remove_child(blur_actor); + + // disconnect the signals about overview animation etc + this.connections.disconnect_all_for(window_actor); + } + } + } + } + + disable() { + this._log("removing blur from applications..."); + + this.service?.unexport(); + + this.blur_actor_map.forEach(((_blur_actor, pid) => { + this.remove_blur(pid); + })); + + this.connections.disconnect_all(); + this.paint_signals.disconnect_all(); + } + + /// Update the opacity of all window actors. + set_opacity() { + let opacity = this.prefs.applications.OPACITY; + + this.window_map.forEach(((meta_window, _pid) => { + let window_actor = meta_window.get_compositor_private(); + this.set_window_opacity(window_actor, opacity); + })); + } + + /// Updates each blur effect to use new sigma value + // FIXME set_sigma and set_brightness are called when the extension is + // loaded and when sigma is changed, and do not respect the per-app + // xprop behaviour + set_sigma(s) { + this.blur_actor_map.forEach((actor, _) => { + actor.get_effect('blur-effect').set_sigma(s); + }); + } + + /// Updates each blur effect to use new brightness value + set_brightness(b) { + this.blur_actor_map.forEach((actor, _) => { + actor.get_effect('blur-effect').set_brightness(b); + }); + } + + // not implemented for dynamic blur + set_color(c) { } + set_noise_amount(n) { } + set_noise_lightness(l) { } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > applications] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/dash_to_dock.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/dash_to_dock.js new file mode 100644 index 0000000..a4bdfad --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/dash_to_dock.js @@ -0,0 +1,320 @@ +'use strict'; + +const { St, Shell, GLib } = imports.gi; +const Main = imports.ui.main; +const Signals = imports.signals; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { PaintSignals } = Me.imports.effects.paint_signals; + +const DASH_STYLES = [ + "transparent-dash", + "light-dash", + "dark-dash" +]; + + +/// 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, prefs) { + // the parent DashBlur object, to communicate + this.dash_blur = dash_blur; + // the blurred dash + this.dash = dash; + this.background_parent = background_parent; + this.effect = effect; + this.prefs = prefs; + 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) + ); + }); + + dash_blur.connections.connect(dash_blur, 'update-sigma', () => { + this.effect.sigma = this.dash_blur.sigma; + }); + + 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_STYLES.forEach( + style => this.dash.remove_style_class_name(style) + ); + + this.dash.set_style_class_name( + DASH_STYLES[this.prefs.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, 'show', () => { + this.effect.sigma = this.dash_blur.sigma; + }); + + dash_blur.connections.connect(dash_blur, 'hide', () => { + this.effect.sigma = 0; + }); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > dash] ${str}`); + } +} + +var DashBlur = class DashBlur { + constructor(connections, prefs) { + this.dashes = []; + this.connections = connections; + this.prefs = prefs; + this.paint_signals = new PaintSignals(connections); + this.sigma = this.prefs.dash_to_dock.CUSTOMIZE + ? this.prefs.dash_to_dock.SIGMA + : this.prefs.SIGMA; + this.brightness = this.prefs.dash_to_dock.CUSTOMIZE + ? this.prefs.dash_to_dock.BRIGHTNESS + : this.prefs.BRIGHTNESS; + this.enabled = false; + } + + enable() { + this.connections.connect(Main.uiGroup, 'actor-added', (_, actor) => { + if ( + (actor.get_name() === "dashtodockContainer") && + (actor.constructor.name === 'DashToDock') + ) + this.try_blur(actor); + }); + + this.blur_existing_dashes(); + this.connect_to_overview(); + + this.enabled = true; + } + + // Finds all existing dashes on every monitor, and call `try_blur` on them + // We cannot only blur `Main.overview.dash`, as there could be several + blur_existing_dashes() { + this._log("searching for dash"); + + // blur every dash found, filtered by name + Main.uiGroup.get_children().filter((child) => { + return (child.get_name() === "dashtodockContainer") && + (child.constructor.name === 'DashToDock'); + }).forEach(this.try_blur.bind(this)); + } + + // Tries to blur the dash contained in the given actor + try_blur(dash_container) { + let dash_box = dash_container._slider.get_child(); + + // verify that we did not already blur that dash + if (!dash_box.get_children().some((child) => { + return child.get_name() === "dash-blurred-background-parent"; + })) { + this._log("dash to dock found, blurring it"); + + // finally blur the dash + let dash = dash_box.get_children().find(child => { + return child.get_name() === 'dash'; + }); + + this.dashes.push(this.blur_dash_from(dash, dash_container)); + } + } + + // 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', + style_class: 'dash-blurred-background-parent', + width: 0, + 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, + }); + + // 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.connections.connect(dash, 'notify::height', _ => { + background.height = dash.height; + }); + + // 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.prefs.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._log(`${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._log(`${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.prefs.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.prefs + ); + + // update the background + this.update_background(); + + // returns infos + return infos; + } + + /// Connect when overview if opened/closed to hide/show the blur accordingly + connect_to_overview() { + this.connections.disconnect_all_for(Main.overview); + + if (this.prefs.dash_to_dock.UNBLUR_IN_OVERVIEW) { + this.connections.connect( + Main.overview, 'showing', this.hide.bind(this) + ); + this.connections.connect( + Main.overview, 'hidden', this.show.bind(this) + ); + } + }; + + /// Updates the background to either remove it or not, according to the + /// user preferences. + update_background() { + if (this.prefs.dash_to_dock.OVERRIDE_BACKGROUND) + this.emit('override-background', true); + else + this.emit('reset-background', true); + } + + set_sigma(sigma) { + this.sigma = sigma; + this.emit('update-sigma', true); + } + + set_brightness(brightness) { + this.brightness = brightness; + this.emit('update-brightness', true); + } + + // not implemented for dynamic blur + set_color(c) { } + set_noise_amount(n) { } + set_noise_lightness(l) { } + + disable() { + this._log("removing blur from dashes"); + + this.emit('remove-dashes', true); + + this.dashes = []; + this.connections.disconnect_all(); + + this.enabled = false; + } + + show() { + this.emit('show', true); + } + hide() { + this.emit('hide', true); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > dash manager] ${str}`); + } +}; + +Signals.addSignalMethods(DashBlur.prototype); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/lockscreen.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/lockscreen.js new file mode 100644 index 0000000..b52acb6 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/lockscreen.js @@ -0,0 +1,171 @@ +'use strict'; + +const { St, Shell } = imports.gi; +const Main = imports.ui.main; +const Background = imports.ui.background; +const UnlockDialog = imports.ui.unlockDialog.UnlockDialog; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const ColorEffect = Me.imports.effects.color_effect.ColorEffect; +const NoiseEffect = Me.imports.effects.noise_effect.NoiseEffect; + +let sigma; +let brightness; +let color; +let noise; +let lightness; + +const original_createBackground = + UnlockDialog.prototype._createBackground; +const original_updateBackgroundEffects = + UnlockDialog.prototype._updateBackgroundEffects; + + +var LockscreenBlur = class LockscreenBlur { + constructor(connections, prefs) { + this.connections = connections; + this.prefs = prefs; + } + + enable() { + this._log("blurring lockscreen"); + + brightness = this.prefs.lockscreen.CUSTOMIZE + ? this.prefs.lockscreen.BRIGHTNESS + : this.prefs.BRIGHTNESS; + sigma = this.prefs.lockscreen.CUSTOMIZE + ? this.prefs.lockscreen.SIGMA + : this.prefs.SIGMA; + color = this.prefs.lockscreen.CUSTOMIZE + ? this.prefs.lockscreen.COLOR + : this.prefs.COLOR; + noise = this.prefs.lockscreen.CUSTOMIZE + ? this.prefs.lockscreen.NOISE_AMOUNT + : this.prefs.NOISE_AMOUNT; + lightness = this.prefs.lockscreen.CUSTOMIZE + ? this.prefs.lockscreen.NOISE_LIGHTNESS + : this.prefs.NOISE_LIGHTNESS; + + this.update_lockscreen(); + } + + update_lockscreen() { + UnlockDialog.prototype._createBackground = + this._createBackground; + UnlockDialog.prototype._updateBackgroundEffects = + this._updateBackgroundEffects; + } + + _createBackground(monitorIndex) { + let monitor = Main.layoutManager.monitors[monitorIndex]; + let widget = new St.Widget({ + style_class: "screen-shield-background", + x: monitor.x, + y: monitor.y, + width: monitor.width, + height: monitor.height, + }); + + let blur_effect = new Shell.BlurEffect({ + name: 'blur', + sigma: sigma, + brightness: brightness + }); + + // store the scale in the effect in order to retrieve later + blur_effect.scale = monitor.geometry_scale; + + let color_effect = new ColorEffect({ + name: 'color', + color: color + }); + + let noise_effect = new NoiseEffect({ + name: 'noise', + noise: noise, + lightness: lightness + }); + + widget.add_effect(color_effect); + widget.add_effect(noise_effect); + widget.add_effect(blur_effect); + + let bgManager = new Background.BackgroundManager({ + container: widget, + monitorIndex, + controlPosition: false, + }); + + this._bgManagers.push(bgManager); + + this._backgroundGroup.add_child(widget); + } + + _updateBackgroundEffects() { + for (const widget of this._backgroundGroup) { + const color_effect = widget.get_effect('blur'); + const noise_effect = widget.get_effect('blur'); + const blur_effect = widget.get_effect('blur'); + + if (color_effect) + color_effect.set({ + color: color + }); + + if (noise_effect) { + noise_effect.set({ + noise: noise, + lightness: lightness, + }); + } + + if (blur_effect) { + blur_effect.set({ + brightness: brightness, + sigma: sigma * blur_effect.scale, + }); + } + } + } + + set_sigma(s) { + sigma = s; + this.update_lockscreen(); + } + + set_brightness(b) { + brightness = b; + this.update_lockscreen(); + } + + set_color(c) { + color = c; + this.update_lockscreen(); + } + + set_noise_amount(n) { + noise = n; + this.update_lockscreen(); + } + + set_noise_lightness(l) { + lightness = l; + this.update_lockscreen(); + } + + disable() { + this._log("removing blur from lockscreen"); + + UnlockDialog.prototype._createBackground = + original_createBackground; + UnlockDialog.prototype._updateBackgroundEffects = + original_updateBackgroundEffects; + + this.connections.disconnect_all(); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > lockscreen] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/overview.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/overview.js new file mode 100644 index 0000000..4217822 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/overview.js @@ -0,0 +1,294 @@ +'use strict'; + +const { Shell, Gio, Meta } = imports.gi; +const Main = imports.ui.main; + +const { WorkspaceAnimationController } = imports.ui.workspaceAnimation; +const wac_proto = WorkspaceAnimationController.prototype; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const ColorEffect = Me.imports.effects.color_effect.ColorEffect; +const NoiseEffect = Me.imports.effects.noise_effect.NoiseEffect; + +const OVERVIEW_COMPONENTS_STYLE = [ + "", + "overview-components-light", + "overview-components-dark", + "overview-components-transparent" +]; + + +var OverviewBlur = class OverviewBlur { + constructor(connections, prefs) { + this.connections = connections; + this.effects = []; + this.prefs = prefs; + this._workspace_switch_bg_actors = []; + this.enabled = false; + } + + enable() { + this._log("blurring overview"); + + // 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._log("updated background"); + this.update_backgrounds(); + } + ); + + // connect to monitors change + this.connections.connect( + Main.layoutManager, + 'monitors-changed', + _ => { + if (Main.screenShield && !Main.screenShield.locked) { + this._log("changed monitors"); + this.update_backgrounds(); + } + } + ); + + // add css class name for workspace-switch background + Main.uiGroup.add_style_class_name("blurred-overview"); + + // add css class name to make components semi-transparent if wanted + this.update_components_classname(); + + // update backgrounds when the component is enabled + this.update_backgrounds(); + + + // part for the workspace animation switch + + // make sure not to do this part if the extension was enabled prior, as + // the functions would call themselves and cause infinite recursion + if (!this.enabled) { + // store original workspace switching methods for restoring them on + // disable() + this._original_PrepareSwitch = wac_proto._prepareWorkspaceSwitch; + this._original_FinishSwitch = wac_proto._finishWorkspaceSwitch; + + const w_m = global.workspace_manager; + const outer_this = this; + + // create a blurred background actor for each monitor during a workspace + // switch + wac_proto._prepareWorkspaceSwitch = function (...params) { + outer_this._log("prepare workspace switch"); + outer_this._original_PrepareSwitch.apply(this, params); + + // this permits to show the blur behind windows that are on + // workspaces on the left and right + if ( + outer_this.prefs.applications.BLUR + ) { + let ws_index = w_m.get_active_workspace_index(); + [ws_index - 1, ws_index + 1].forEach( + i => w_m.get_workspace_by_index(i)?.list_windows().forEach( + window => window.get_compositor_private().show() + ) + ); + } + + Main.layoutManager.monitors.forEach(monitor => { + if ( + !( + Meta.prefs_get_workspaces_only_on_primary() && + (monitor !== Main.layoutManager.primaryMonitor) + ) + ) { + const bg_actor = outer_this.create_background_actor( + monitor + ); + + Main.uiGroup.insert_child_above( + bg_actor, + global.window_group + ); + + // store the actors so that we can delete them later + outer_this._workspace_switch_bg_actors.push(bg_actor); + } + }); + }; + + // remove the workspace-switch actors when the switch is done + wac_proto._finishWorkspaceSwitch = function (...params) { + outer_this._log("finish workspace switch"); + outer_this._original_FinishSwitch.apply(this, params); + + // this hides windows that are not on the current workspace + if ( + outer_this.prefs.applications.BLUR + ) + for (let i = 0; i < w_m.get_n_workspaces(); i++) { + if (i != w_m.get_active_workspace_index()) + w_m.get_workspace_by_index(i)?.list_windows().forEach( + window => window.get_compositor_private().hide() + ); + } + + outer_this._workspace_switch_bg_actors.forEach(actor => { + actor.destroy(); + }); + outer_this._workspace_switch_bg_actors = []; + }; + } + + this.enabled = true; + } + + update_backgrounds() { + // remove every old background + Main.layoutManager.overviewGroup.get_children().forEach(actor => { + if (actor.constructor.name === 'Meta_BackgroundActor') { + Main.layoutManager.overviewGroup.remove_child(actor); + actor.destroy(); + } + }); + this.effects = []; + + // add new backgrounds + Main.layoutManager.monitors.forEach(monitor => { + const bg_actor = this.create_background_actor(monitor); + + Main.layoutManager.overviewGroup.insert_child_at_index( + bg_actor, + monitor.index + ); + }); + } + + create_background_actor(monitor) { + let bg_actor = new Meta.BackgroundActor; + let background = Main.layoutManager._backgroundGroup.get_child_at_index( + Main.layoutManager.monitors.length - monitor.index - 1 + ); + + if (!background) { + this._log("could not get background for overview"); + return bg_actor; + } + + bg_actor.set_content(background.get_content()); + + let blur_effect = new Shell.BlurEffect({ + brightness: this.prefs.overview.CUSTOMIZE + ? this.prefs.overview.BRIGHTNESS + : this.prefs.BRIGHTNESS, + sigma: this.prefs.overview.CUSTOMIZE + ? this.prefs.overview.SIGMA + : this.prefs.SIGMA + * monitor.geometry_scale, + mode: Shell.BlurMode.ACTOR + }); + + // store the scale in the effect in order to retrieve it in set_sigma + blur_effect.scale = monitor.geometry_scale; + + let color_effect = new ColorEffect({ + color: this.prefs.overview.CUSTOMIZE + ? this.prefs.overview.COLOR + : this.prefs.COLOR + }); + + let noise_effect = new NoiseEffect({ + noise: this.prefs.overview.CUSTOMIZE + ? this.prefs.overview.NOISE_AMOUNT + : this.prefs.NOISE_AMOUNT, + lightness: this.prefs.overview.CUSTOMIZE + ? this.prefs.overview.NOISE_LIGHTNESS + : this.prefs.NOISE_LIGHTNESS + }); + + bg_actor.add_effect(color_effect); + bg_actor.add_effect(noise_effect); + bg_actor.add_effect(blur_effect); + this.effects.push({ blur_effect, color_effect, noise_effect }); + + bg_actor.set_x(monitor.x); + bg_actor.set_y(monitor.y); + + return bg_actor; + } + + /// Updates the classname to style overview components with semi-transparent + /// backgrounds. + update_components_classname() { + OVERVIEW_COMPONENTS_STYLE.forEach( + style => Main.uiGroup.remove_style_class_name(style) + ); + + Main.uiGroup.add_style_class_name( + OVERVIEW_COMPONENTS_STYLE[this.prefs.overview.STYLE_COMPONENTS] + ); + } + + set_sigma(s) { + this.effects.forEach(effect => { + effect.blur_effect.sigma = s * effect.blur_effect.scale; + }); + } + + set_brightness(b) { + this.effects.forEach(effect => { + effect.blur_effect.brightness = b; + }); + } + + set_color(c) { + this.effects.forEach(effect => { + effect.color_effect.color = c; + }); + } + + set_noise_amount(n) { + this.effects.forEach(effect => { + effect.noise_effect.noise = n; + }); + } + + set_noise_lightness(l) { + this.effects.forEach(effect => { + effect.noise_effect.lightness = l; + }); + } + + disable() { + this._log("removing blur from overview"); + Main.layoutManager.overviewGroup.get_children().forEach(actor => { + if (actor.constructor.name === 'Meta_BackgroundActor') { + Main.layoutManager.overviewGroup.remove_child(actor); + } + }); + Main.uiGroup.remove_style_class_name("blurred-overview"); + OVERVIEW_COMPONENTS_STYLE.forEach( + style => Main.uiGroup.remove_style_class_name(style) + ); + + // make sure to absolutely not do this if the component was not enabled + // prior, as this would cause infinite recursion + if (this.enabled) { + // restore original behavior + if (this._original_PrepareSwitch) + wac_proto._prepareWorkspaceSwitch = this._original_PrepareSwitch; + if (this._original_FinishSwitch) + wac_proto._finishWorkspaceSwitch = this._original_FinishSwitch; + } + + this.effects = []; + this.connections.disconnect_all(); + this.enabled = false; + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > overview] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/panel.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/panel.js new file mode 100644 index 0000000..5df1756 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/panel.js @@ -0,0 +1,660 @@ +'use strict'; + +const { St, Shell, Meta, Gio, GLib } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { PaintSignals } = Me.imports.effects.paint_signals; +const ColorEffect = Me.imports.effects.color_effect.ColorEffect; +const NoiseEffect = Me.imports.effects.noise_effect.NoiseEffect; + +const DASH_TO_PANEL_UUID = 'dash-to-panel@jderose9.github.com'; + +const PANEL_STYLES = [ + "transparent-panel", + "light-panel", + "dark-panel" +]; + + +var PanelBlur = class PanelBlur { + constructor(connections, prefs) { + this.connections = connections; + this.window_signal_ids = new Map(); + this.prefs = prefs; + this.actors_list = []; + this.enabled = false; + } + + enable() { + this._log("blurring top panel"); + + // check for panels when Dash to Panel is activated + this.connections.connect( + Main.extensionManager, + 'extension-state-changed', + (_, extension) => { + if (extension.uuid === DASH_TO_PANEL_UUID + && extension.state === 1 + ) { + this.connections.connect( + global.dashToPanel, + 'panels-created', + _ => this.blur_dtp_panels() + ); + + this.blur_existing_panels(); + } + } + ); + + this.blur_existing_panels(); + + // connect to overview being opened/closed, and dynamically show or not + // the blur when a window is near a panel + this.connect_to_windows_and_overview(); + + // 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.actors_list.forEach(actors => + this.update_wallpaper(actors) + ) + ); + + // connect to monitors change + this.connections.connect( + Main.layoutManager, + 'monitors-changed', + _ => { + if (Main.screenShield && !Main.screenShield.locked) { + this.reset(); + } + } + ); + + this.enabled = true; + } + + reset() { + this._log("resetting..."); + + this.disable(); + setTimeout(_ => this.enable(), 1); + } + + /// Check for already existing panels and blur them if they are not already + blur_existing_panels() { + // check if dash-to-panel is present + if (global.dashToPanel) { + // blur already existing ones + if (global.dashToPanel.panels) + this.blur_dtp_panels(); + } else { + // if no dash-to-panel, blur the main and only panel + this.maybe_blur_panel(Main.panel); + } + } + + blur_dtp_panels() { + // FIXME when Dash to Panel changes its size, it seems it creates new + // panels; but I can't get to delete old widgets + + // blur every panel found + global.dashToPanel.panels.forEach(p => { + this.maybe_blur_panel(p.panel); + }); + + // if main panel is not included in the previous panels, blur it + if ( + !global.dashToPanel.panels + .map(p => p.panel) + .includes(Main.panel) + ) + this.maybe_blur_panel(Main.panel); + }; + + /// Blur a panel only if it is not already blurred (contained in the list) + maybe_blur_panel(panel) { + // check if the panel is contained in the list + let actors = this.actors_list.find( + actors => actors.widgets.panel == panel + ); + + if (!actors) + // if the actors is not blurred, blur it + this.blur_panel(panel); + else + // if it is blurred, update the blur anyway + this.change_blur_type(actors); + } + + /// Blur a panel + blur_panel(panel) { + let panel_box = panel.get_parent(); + let is_dtp_panel = false; + if (!panel_box.name) { + is_dtp_panel = true; + panel_box = panel_box.get_parent(); + } + + let monitor = this.find_monitor_for(panel); + if (!monitor) + return; + + let background_parent = new St.Widget({ + name: 'topbar-blurred-background-parent', + x: 0, y: 0, width: 0, height: 0 + }); + + let background = this.prefs.panel.STATIC_BLUR + ? new Meta.BackgroundActor + : new St.Widget; + + background_parent.add_child(background); + + // insert background parent + panel_box.insert_child_at_index(background_parent, 0); + + let blur = new Shell.BlurEffect({ + brightness: this.prefs.panel.CUSTOMIZE + ? this.prefs.panel.BRIGHTNESS + : this.prefs.BRIGHTNESS, + sigma: this.prefs.panel.CUSTOMIZE + ? this.prefs.panel.SIGMA + : this.prefs.SIGMA + * monitor.geometry_scale, + mode: this.prefs.panel.STATIC_BLUR + ? Shell.BlurMode.ACTOR + : Shell.BlurMode.BACKGROUND + }); + + // store the scale in the effect in order to retrieve it in set_sigma + blur.scale = monitor.geometry_scale; + + let color = new ColorEffect({ + color: this.prefs.panel.CUSTOMIZE + ? this.prefs.panel.COLOR + : this.prefs.COLOR + }); + + let noise = new NoiseEffect({ + noise: this.prefs.panel.CUSTOMIZE + ? this.prefs.panel.NOISE_AMOUNT + : this.prefs.NOISE_AMOUNT, + lightness: this.prefs.panel.CUSTOMIZE + ? this.prefs.panel.NOISE_LIGHTNESS + : this.prefs.NOISE_LIGHTNESS + }); + + let paint_signals = new PaintSignals(this.connections); + + let actors = { + widgets: { panel, panel_box, background, background_parent }, + effects: { blur, color, noise }, + paint_signals, + monitor, + is_dtp_panel + }; + + this.actors_list.push(actors); + + // perform updates + this.change_blur_type(actors); + + // connect to panel, panel_box and its parent position or size change + // this should fire update_size every time one of its params change + this.connections.connect( + panel, + 'notify::position', + _ => this.update_size(actors) + ); + this.connections.connect( + panel_box, + ['notify::size', 'notify::position'], + _ => this.update_size(actors) + ); + this.connections.connect( + panel_box.get_parent(), + 'notify::position', + _ => this.update_size(actors) + ); + } + + update_all_blur_type() { + this.actors_list.forEach(actors => this.change_blur_type(actors)); + } + + change_blur_type(actors) { + let is_static = this.prefs.panel.STATIC_BLUR; + + // reset widgets to right state + actors.widgets.background_parent.remove_child(actors.widgets.background); + actors.widgets.background.remove_effect(actors.effects.blur); + actors.widgets.background.remove_effect(actors.effects.color); + actors.widgets.background.remove_effect(actors.effects.noise); + + // create new background actor + actors.widgets.background = is_static + ? new Meta.BackgroundActor + : new St.Widget; + + // change blur mode + actors.effects.blur.set_mode(is_static ? 0 : 1); + + // disable other effects if the blur is dynamic, as they makes it opaque + actors.effects.color._static = is_static; + actors.effects.noise._static = is_static; + actors.effects.color.update_enabled(); + actors.effects.noise.update_enabled(); + + // add the effects in order + actors.widgets.background.add_effect(actors.effects.color); + actors.widgets.background.add_effect(actors.effects.noise); + actors.widgets.background.add_effect(actors.effects.blur); + + // add the background actor behing the panel + actors.widgets.background_parent.add_child(actors.widgets.background); + + // perform updates + this.update_wallpaper(actors); + this.update_size(actors); + + + // 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 (!is_static) { + if (this.prefs.HACKS_LEVEL === 1) { + this._log("panel hack level 1"); + actors.paint_signals.disconnect_all(); + + let rp = () => { actors.effects.blur.queue_repaint(); }; + + this.connections.connect(actors.widgets.panel, [ + 'enter-event', 'leave-event', 'button-press-event' + ], rp); + + actors.widgets.panel.get_children().forEach(child => { + this.connections.connect(child, [ + 'enter-event', 'leave-event', 'button-press-event' + ], rp); + }); + } else if (this.prefs.HACKS_LEVEL === 2) { + this._log("panel hack level 2"); + actors.paint_signals.disconnect_all(); + + actors.paint_signals.connect( + actors.widgets.background, actors.effects.blur + ); + } else { + actors.paint_signals.disconnect_all(); + } + } + } + + update_wallpaper(actors) { + // if static blur, get right wallpaper and update blur with it + if (this.prefs.panel.STATIC_BLUR) { + let bg = Main.layoutManager._backgroundGroup.get_child_at_index( + Main.layoutManager.monitors.length + - this.find_monitor_for(actors.widgets.panel).index - 1 + ); + if (bg) + actors.widgets.background.set_content(bg.get_content()); + else + this._log("could not get background for panel"); + } + } + + update_size(actors) { + let panel = actors.widgets.panel; + let panel_box = actors.widgets.panel_box; + let background = actors.widgets.background; + let monitor = this.find_monitor_for(panel); + if (!monitor) + return; + + let [width, height] = panel_box.get_size(); + background.width = width; + background.height = height; + + // if static blur, need to clip the background + if (this.prefs.panel.STATIC_BLUR) { + // an alternative to panel.get_transformed_position, because it + // sometimes yields NaN (probably when the actor is not fully + // positionned yet) + let [p_x, p_y] = panel_box.get_position(); + let [p_p_x, p_p_y] = panel_box.get_parent().get_position(); + let x = p_x + p_p_x - monitor.x; + let y = p_y + p_p_y - monitor.y; + + background.set_clip(x, y, width, height); + background.x = -x; + background.y = -y; + + // fixes a bug where the blur is washed away when changing the sigma + this.invalidate_blur(actors); + } else { + background.x = panel.x; + background.y = panel.y; + } + + // update the monitor panel is on + actors.monitor = this.find_monitor_for(panel); + } + + /// An helper function to find the monitor in which an actor is situated, + /// there might be a pre-existing function in GLib already + find_monitor_for(actor) { + let extents = actor.get_transformed_extents(); + let rect = new Meta.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]; + } + + /// Connect when overview if opened/closed to hide/show the blur accordingly + /// + /// If HIDETOPBAR is set, we need just to hide the blur when showing appgrid + /// (so no shadow is cropped) + connect_to_overview() { + // may be called when panel blur is disabled, if hidetopbar + // compatibility is toggled on/off + // if this is the case, do nothing as only the panel blur interfers with + // hidetopbar + if ( + this.prefs.panel.BLUR && + this.prefs.panel.UNBLUR_IN_OVERVIEW + ) { + if (!this.prefs.hidetopbar.COMPATIBILITY) { + this.connections.connect( + Main.overview, 'showing', this.hide.bind(this) + ); + this.connections.connect( + Main.overview, 'hidden', this.show.bind(this) + ); + } else { + let appDisplay = Main.overview._overview._controls._appDisplay; + + this.connections.connect( + appDisplay, 'show', this.hide.bind(this) + ); + this.connections.connect( + appDisplay, 'hide', this.show.bind(this) + ); + } + + } + } + + /// Connect to windows disable transparency when a window is too close + connect_to_windows() { + if ( + this.prefs.panel.OVERRIDE_BACKGROUND_DYNAMICALLY + ) { + // connect to overview opening/closing + this.connections.connect(Main.overview, ['showing', 'hiding'], + this.update_visibility.bind(this) + ); + + // connect to session mode update + this.connections.connect(Main.sessionMode, 'updated', + this.update_visibility.bind(this) + ); + + // manage already-existing windows + for (const meta_window_actor of global.get_window_actors()) { + this.on_window_actor_added( + meta_window_actor.get_parent(), meta_window_actor + ); + } + + // manage windows at their creation/removal + this.connections.connect(global.window_group, 'actor-added', + this.on_window_actor_added.bind(this) + ); + this.connections.connect(global.window_group, 'actor-removed', + this.on_window_actor_removed.bind(this) + ); + + // connect to a workspace change + this.connections.connect(global.window_manager, 'switch-workspace', + this.update_visibility.bind(this) + ); + + // perform early update + this.update_visibility(); + } else { + // reset transparency for every panels + this.actors_list.forEach( + actors => this.set_should_override_panel(actors, true) + ); + } + } + + /// An helper to connect to both the windows and overview signals. + /// This is the only function that should be directly called, to prevent + /// inconsistencies with signals not being disconnected. + connect_to_windows_and_overview() { + this.disconnect_from_windows_and_overview(); + this.connect_to_overview(); + this.connect_to_windows(); + } + + /// Disconnect all the connections created by connect_to_windows + disconnect_from_windows_and_overview() { + // disconnect the connections to actors + for (const actor of [ + Main.overview, Main.sessionMode, + global.window_group, global.window_manager, + Main.overview._overview._controls._appDisplay + ]) { + this.connections.disconnect_all_for(actor); + } + + // disconnect the connections from windows + for (const [actor, ids] of this.window_signal_ids) { + for (const id of ids) { + actor.disconnect(id); + } + } + this.window_signal_ids = new Map(); + } + + /// Callback when a new window is added + on_window_actor_added(container, meta_window_actor) { + this.window_signal_ids.set(meta_window_actor, [ + meta_window_actor.connect('notify::allocation', + _ => this.update_visibility() + ), + meta_window_actor.connect('notify::visible', + _ => this.update_visibility() + ) + ]); + this.update_visibility(); + } + + /// Callback when a window is removed + on_window_actor_removed(container, meta_window_actor) { + for (const signalId of this.window_signal_ids.get(meta_window_actor)) { + meta_window_actor.disconnect(signalId); + } + this.window_signal_ids.delete(meta_window_actor); + this.update_visibility(); + } + + /// Update the visibility of the blur effect + update_visibility() { + if ( + Main.panel.has_style_pseudo_class('overview') + || !Main.sessionMode.hasWindows + ) { + this.actors_list.forEach( + actors => this.set_should_override_panel(actors, true) + ); + return; + } + + if (!Main.layoutManager.primaryMonitor) + return; + + // get all the windows in the active workspace that are visible + const workspace = global.workspace_manager.get_active_workspace(); + const windows = workspace.list_windows().filter(meta_window => + meta_window.showing_on_its_workspace() + && !meta_window.is_hidden() + && meta_window.get_window_type() !== Meta.WindowType.DESKTOP + // exclude Desktop Icons NG + && meta_window.get_gtk_application_id() !== "com.rastersoft.ding" + ); + + // check if at least one window is near enough to each panel and act + // accordingly + const scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; + this.actors_list + // do not apply for dtp panels, as it would only cause bugs and it + // can be done from its preferences anyway + .filter(actors => !actors.is_dtp_panel) + .forEach(actors => { + let panel = actors.widgets.panel; + let panel_top = panel.get_transformed_position()[1]; + let panel_bottom = panel_top + panel.get_height(); + + // check if at least a window is near enough the panel + let window_overlap_panel = false; + windows.forEach(meta_window => { + let window_monitor_i = meta_window.get_monitor(); + let same_monitor = actors.monitor.index == window_monitor_i; + + let window_vertical_pos = meta_window.get_frame_rect().y; + + // if so, and if in the same monitor, then it overlaps + if (same_monitor + && + window_vertical_pos < panel_bottom + 5 * scale + ) + window_overlap_panel = true; + }); + + // if no window overlaps, then the panel is transparent + this.set_should_override_panel( + actors, !window_overlap_panel + ); + }); + } + + /// Choose wether or not the panel background should be overriden, in + /// respect to its argument and the `override-background` setting. + set_should_override_panel(actors, should_override) { + let panel = actors.widgets.panel; + + PANEL_STYLES.forEach(style => panel.remove_style_class_name(style)); + + if ( + this.prefs.panel.OVERRIDE_BACKGROUND + && + should_override + ) + panel.add_style_class_name( + PANEL_STYLES[this.prefs.panel.STYLE_PANEL] + ); + } + + /// Fixes a bug where the blur is washed away when changing the sigma, or + /// enabling/disabling other effects. + invalidate_blur(actors) { + if (this.prefs.panel.STATIC_BLUR && actors.widgets.background) + actors.widgets.background.get_content().invalidate(); + } + + invalidate_all_blur() { + this.actors_list.forEach(actors => this.invalidate_blur(actors)); + } + + set_sigma(s) { + this.actors_list.forEach(actors => { + actors.effects.blur.sigma = s * actors.effects.blur.scale; + this.invalidate_blur(actors); + }); + } + + set_brightness(b) { + this.actors_list.forEach(actors => { + actors.effects.blur.brightness = b; + }); + } + + set_color(c) { + this.actors_list.forEach(actors => { + actors.effects.color.color = c; + }); + } + + set_noise_amount(n) { + this.actors_list.forEach(actors => { + actors.effects.noise.noise = n; + }); + } + + set_noise_lightness(l) { + this.actors_list.forEach(actors => { + actors.effects.noise.lightness = l; + }); + } + + show() { + this.actors_list.forEach(actors => { + actors.widgets.background_parent.show(); + }); + } + + hide() { + this.actors_list.forEach(actors => { + actors.widgets.background_parent.hide(); + }); + } + + disable() { + this._log("removing blur from top panel"); + + this.disconnect_from_windows_and_overview(); + + this.actors_list.forEach(actors => { + this.set_should_override_panel(actors, false); + try { + actors.widgets.panel_box.remove_child( + actors.widgets.background_parent + ); + } catch (e) { } + + }); + + this.actors_list = []; + + this.connections.disconnect_all(); + + this.enabled = false; + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > panel] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/screenshot.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/screenshot.js new file mode 100644 index 0000000..333eccd --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/screenshot.js @@ -0,0 +1,166 @@ +'use strict'; + +const { Shell, Gio, Meta } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const ColorEffect = Me.imports.effects.color_effect.ColorEffect; +const NoiseEffect = Me.imports.effects.noise_effect.NoiseEffect; + + +var ScreenshotBlur = class ScreenshotBlur { + constructor(connections, prefs) { + this.connections = connections; + this.effects = []; + this.prefs = prefs; + } + + enable() { + this._log("blurring screenshot's window selector"); + + // 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._log("updated background for screenshot's window selector"); + this.update_backgrounds(); + } + ); + + // connect to monitors change + this.connections.connect( + Main.layoutManager, + 'monitors-changed', + _ => { + if (Main.screenShield && !Main.screenShield.locked) { + this._log("changed monitors for screenshot's window selector"); + this.update_backgrounds(); + } + } + ); + + // update backgrounds when the component is enabled + this.update_backgrounds(); + } + + update_backgrounds() { + // remove every old background + this.remove(); + + // add new backgrounds + for (let i = 0; i < Main.screenshotUI._windowSelectors.length; i++) { + const actor = Main.screenshotUI._windowSelectors[i]; + const monitor = Main.layoutManager.monitors[i]; + + if (!monitor) + continue; + + const bg_actor = this.create_background_actor(monitor); + actor.insert_child_at_index(bg_actor, 0); + actor._blur_actor = bg_actor; + } + } + + create_background_actor(monitor) { + let bg_actor = new Meta.BackgroundActor; + let background = Main.layoutManager._backgroundGroup.get_child_at_index( + Main.layoutManager.monitors.length - monitor.index - 1 + ); + + if (!background) { + this._log("could not get background for screenshot's window selector"); + return bg_actor; + } + + bg_actor.set_content(background.get_content()); + + let blur_effect = new Shell.BlurEffect({ + brightness: this.prefs.screenshot.CUSTOMIZE + ? this.prefs.screenshot.BRIGHTNESS + : this.prefs.BRIGHTNESS, + sigma: this.prefs.screenshot.CUSTOMIZE + ? this.prefs.screenshot.SIGMA + : this.prefs.SIGMA + * monitor.geometry_scale, + mode: Shell.BlurMode.ACTOR + }); + + // store the scale in the effect in order to retrieve it in set_sigma + blur_effect.scale = monitor.geometry_scale; + + let color_effect = new ColorEffect({ + color: this.prefs.screenshot.CUSTOMIZE + ? this.prefs.screenshot.COLOR + : this.prefs.COLOR + }); + + let noise_effect = new NoiseEffect({ + noise: this.prefs.screenshot.CUSTOMIZE + ? this.prefs.screenshot.NOISE_AMOUNT + : this.prefs.NOISE_AMOUNT, + lightness: this.prefs.screenshot.CUSTOMIZE + ? this.prefs.screenshot.NOISE_LIGHTNESS + : this.prefs.NOISE_LIGHTNESS + }); + + bg_actor.add_effect(color_effect); + bg_actor.add_effect(noise_effect); + bg_actor.add_effect(blur_effect); + this.effects.push({ blur_effect, color_effect, noise_effect }); + + return bg_actor; + } + + set_sigma(s) { + this.effects.forEach(effect => { + effect.blur_effect.sigma = s * effect.blur_effect; + }); + } + + set_brightness(b) { + this.effects.forEach(effect => { + effect.blur_effect.brightness = b; + }); + } + + set_color(c) { + this.effects.forEach(effect => { + effect.color_effect.color = c; + }); + } + + set_noise_amount(n) { + this.effects.forEach(effect => { + effect.noise_effect.noise = n; + }); + } + + set_noise_lightness(l) { + this.effects.forEach(effect => { + effect.noise_effect.lightness = l; + }); + } + + remove() { + Main.screenshotUI._windowSelectors.forEach(actor => { + if (actor._blur_actor) + actor.remove_child(actor._blur_actor); + }); + this.effects = []; + } + + disable() { + this._log("removing blur from screenshot's window selector"); + + this.remove(); + this.connections.disconnect_all(); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > screenshot] ${str}`); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/window_list.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/window_list.js new file mode 100644 index 0000000..94883da --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/components/window_list.js @@ -0,0 +1,165 @@ +'use strict'; + +const { St, Shell, Meta, Gio } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const { PaintSignals } = Me.imports.effects.paint_signals; + + +var WindowListBlur = class WindowListBlur { + constructor(connections, prefs) { + this.connections = connections; + this.prefs = prefs; + this.paint_signals = new PaintSignals(connections); + this.effects = []; + } + + enable() { + this._log("blurring window list"); + + // blur if window-list is found + Main.layoutManager.uiGroup.get_children().forEach( + child => this.try_blur(child) + ); + + // listen to new actors in `Main.layoutManager.uiGroup` and blur it if + // if is window-list + this.connections.connect( + Main.layoutManager.uiGroup, + 'actor-added', + (_, child) => this.try_blur(child) + ); + + // connect to overview + this.connections.connect(Main.overview, 'showing', _ => { + this.hide(); + }); + this.connections.connect(Main.overview, 'hidden', _ => { + this.show(); + }); + } + + try_blur(child) { + if ( + child.constructor.name === "WindowList" && + child.style !== "background:transparent;" + ) { + this._log("found window list to blur"); + + let blur_effect = new Shell.BlurEffect({ + name: 'window-list-blur', + sigma: this.prefs.window_list.CUSTOMIZE + ? this.prefs.window_list.SIGMA + : this.prefs.SIGMA, + brightness: this.prefs.window_list.CUSTOMIZE + ? this.prefs.window_list.BRIGHTNESS + : this.prefs.BRIGHTNESS, + mode: Shell.BlurMode.BACKGROUND + }); + + child.set_style("background:transparent;"); + child.add_effect(blur_effect); + this.effects.push({ blur_effect }); + + child._windowList.get_children().forEach( + window => this.blur_window_button(window) + ); + + this.connections.connect( + child._windowList, + 'actor-added', + (_, window) => this.blur_window_button(window) + ); + + + // 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.prefs.HACKS_LEVEL === 1) { + this._log("window list hack level 1"); + + this.paint_signals.connect(child, blur_effect); + + } else if (this.prefs.HACKS_LEVEL === 2) { + this._log("window list hack level 2"); + + this.paint_signals.connect(child, blur_effect); + } else { + this.paint_signals.disconnect_all(); + } + } + } + + blur_window_button(window) { + window.get_child_at_index(0).set_style( + "box-shadow:none; background-color:rgba(0,0,0,0.2); border-radius:5px;" + ); + } + + try_remove_blur(child) { + if ( + child.constructor.name === "WindowList" && + child.style === "background:transparent;" + ) { + child.style = null; + child.remove_effect_by_name('window-list-blur'); + + child._windowList.get_children().forEach( + child => child.get_child_at_index(0).set_style(null) + ); + } + } + + set_sigma(s) { + this.effects.forEach(effect => { + effect.blur_effect.sigma = s; + }); + } + + set_brightness(b) { + this.effects.forEach(effect => { + effect.blur_effect.brightness = b; + }); + } + + // not implemented for dynamic blur + set_color(c) { } + set_noise_amount(n) { } + set_noise_lightness(l) { } + + hide() { + this.set_sigma(0); + } + + show() { + this.set_sigma( + this.prefs.window_list.CUSTOMIZE + ? this.prefs.window_list.SIGMA + : this.prefs.SIGMA + ); + } + + disable() { + this._log("removing blur from window list"); + + Main.layoutManager.uiGroup.get_children().forEach( + child => this.try_remove_blur(child) + ); + + this.effects = []; + this.connections.disconnect_all(); + } + + _log(str) { + if (this.prefs.DEBUG) + log(`[Blur my Shell > window list] ${str}`); + } +}; \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/connections.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/connections.js new file mode 100644 index 0000000..ec2f51f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/connections.js @@ -0,0 +1,104 @@ +'use strict'; + +const GObject = imports.gi.GObject; + +/// An object to easily manage signals. +var Connections = class Connections { + constructor() { + this.buffer = []; + } + + /// Adds a connection. + /// + /// Takes as arguments: + /// - an actor, which fires the signal + /// - signal(s) (string or array of strings), which are watched for + /// - a callback, which is called when the signal is fired + connect(actor, signals, handler) { + if (signals instanceof Array) { + signals.forEach(signal => { + let id = actor.connect(signal, handler); + this.process_connection(actor, id); + }); + } else { + let id = actor.connect(signals, handler); + this.process_connection(actor, id); + } + + } + + /// Process the given actor and id. + /// + /// This makes sure that the signal is disconnected when the actor is + /// destroyed, and that the signal can be managed through other Connections + /// methods. + process_connection(actor, id) { + let infos = { + actor: actor, + id: id + }; + + // remove the signal when the actor is destroyed + if ( + actor.connect && + ( + !(actor instanceof GObject.Object) || + GObject.signal_lookup('destroy', actor) + ) + ) { + let destroy_id = actor.connect('destroy', () => { + actor.disconnect(id); + actor.disconnect(destroy_id); + + let index = this.buffer.indexOf(infos); + if (index >= 0) { + this.buffer.splice(index, 1); + } + }); + } + + this.buffer.push(infos); + } + + /// Disconnects every connection found for an actor. + disconnect_all_for(actor) { + // get every connection stored for the actor + let actor_connections = this.buffer.filter( + infos => infos.actor === actor + ); + + // remove each of them + actor_connections.forEach((connection) => { + // disconnect + try { + connection.actor.disconnect(connection.id); + } catch (e) { + this._log(`error removing connection: ${e}; continuing`); + } + + // remove from buffer + let index = this.buffer.indexOf(connection); + this.buffer.splice(index, 1); + }); + } + + /// Disconnect every connection for each actor. + disconnect_all() { + this.buffer.forEach((connection) => { + // disconnect + try { + connection.actor.disconnect(connection.id); + } catch (e) { + this._log(`error removing connection: ${e}; continuing`); + } + }); + + // reset buffer + this.buffer = []; + } + + _log(str) { + // no need to check if DEBUG here as this._log is only used on error + log(`[Blur my Shell > connections] ${str}`); + } +}; \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/keys.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/keys.js new file mode 100644 index 0000000..beaa8e9 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/keys.js @@ -0,0 +1,131 @@ +'use strict'; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +const { Type } = Me.imports.conveniences.settings; + +// This lists the preferences keys +var Keys = [ + { + component: "general", schemas: [ + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.B, name: "color-and-noise" }, + { type: Type.I, name: "hacks-level" }, + { type: Type.B, name: "debug" }, + ] + }, + { + component: "overview", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.I, name: "style-components" }, + ] + }, + { + component: "appfolder", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.I, name: "style-dialogs" }, + ] + }, + { + component: "panel", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.B, name: "static-blur" }, + { type: Type.B, name: "unblur-in-overview" }, + { type: Type.B, name: "override-background" }, + { type: Type.I, name: "style-panel" }, + { type: Type.B, name: "override-background-dynamically" }, + ] + }, + { + component: "dash-to-dock", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.B, name: "static-blur" }, + { type: Type.B, name: "unblur-in-overview" }, + { type: Type.B, name: "override-background" }, + { type: Type.I, name: "style-dash-to-dock" }, + ] + }, + { + component: "applications", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + { type: Type.I, name: "opacity" }, + { type: Type.B, name: "blur-on-overview" }, + { type: Type.B, name: "enable-all" }, + { type: Type.AS, name: "whitelist" }, + { type: Type.AS, name: "blacklist" }, + ] + }, + { + component: "lockscreen", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + ] + }, + { + component: "window-list", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + ] + }, + { + component: "screenshot", schemas: [ + { type: Type.B, name: "blur" }, + { type: Type.B, name: "customize" }, + { type: Type.I, name: "sigma" }, + { type: Type.D, name: "brightness" }, + { type: Type.C, name: "color" }, + { type: Type.D, name: "noise-amount" }, + { type: Type.D, name: "noise-lightness" }, + ] + }, + { + component: "hidetopbar", schemas: [ + { type: Type.B, name: "compatibility" }, + ] + }, +]; \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/settings.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/settings.js new file mode 100644 index 0000000..5c07472 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/conveniences/settings.js @@ -0,0 +1,185 @@ +'use strict'; + +const { Gio, GLib } = imports.gi; +const Signals = imports.signals; + +const ExtensionUtils = imports.misc.extensionUtils; + +/// An enum non-extensively describing the type of gsettings key. +var Type = { + B: 'Boolean', + I: 'Integer', + D: 'Double', + S: 'String', + C: 'Color', + AS: 'StringArray' +}; + +/// An object to get and manage the gsettings preferences. +/// +/// Should be initialized with an array of keys, for example: +/// +/// let prefs = new Prefs([ +/// { type: Type.I, name: "panel-corner-radius" }, +/// { type: Type.B, name: "debug" } +/// ]); +/// +/// Each {type, name} object represents a gsettings key, which must be created +/// in the gschemas.xml file of the extension. +var Prefs = class Prefs { + constructor(keys) { + let settings = this.settings = ExtensionUtils.getSettings(); + this.keys = keys; + + this.keys.forEach(bundle => { + let component = this; + let component_settings = settings; + if (bundle.component !== "general") { + let bundle_component = bundle.component.replaceAll('-', '_'); + this[bundle_component] = { + settings: this.settings.get_child(bundle.component) + }; + component = this[bundle_component]; + component_settings = settings.get_child(bundle.component); + } + + + bundle.schemas.forEach(key => { + let property_name = this.get_property_name(key.name); + + switch (key.type) { + case Type.B: + Object.defineProperty(component, property_name, { + get() { + return component_settings.get_boolean(key.name); + }, + set(v) { + component_settings.set_boolean(key.name, v); + } + }); + break; + + case Type.I: + Object.defineProperty(component, property_name, { + get() { + return component_settings.get_int(key.name); + }, + set(v) { + component_settings.set_int(key.name, v); + } + }); + break; + + case Type.D: + Object.defineProperty(component, property_name, { + get() { + return component_settings.get_double(key.name); + }, + set(v) { + component_settings.set_double(key.name, v); + } + }); + break; + + case Type.S: + Object.defineProperty(component, property_name, { + get() { + return component_settings.get_string(key.name); + }, + set(v) { + component_settings.set_string(key.name, v); + } + }); + break; + + case Type.C: + Object.defineProperty(component, property_name, { + // returns the array [red, blue, green, alpha] with + // values between 0 and 1 + get() { + let val = component_settings.get_value(key.name); + return val.deep_unpack(); + }, + // takes an array [red, blue, green, alpha] with + // values between 0 and 1 + set(v) { + let val = new GLib.Variant("(dddd)", v); + component_settings.set_value(key.name, val); + } + }); + break; + + case Type.AS: + Object.defineProperty(component, property_name, { + get() { + let val = component_settings.get_value(key.name); + return val.deep_unpack(); + }, + set(v) { + let val = new GLib.Variant("as", v); + component_settings.set_value(key.name, val); + } + }); + break; + } + + component[property_name + '_reset'] = function () { + return component_settings.reset(key.name); + }; + + component[property_name + '_changed'] = function (cb) { + return component_settings.connect('changed::' + key.name, cb); + }; + + component[property_name + '_disconnect'] = function () { + return component_settings.disconnect.apply( + component_settings, arguments + ); + }; + }); + }); + }; + + /// Reset the preferences. + reset() { + this.keys.forEach(bundle => { + let component = this; + if (bundle.component !== "general") { + let bundle_component = bundle.component.replaceAll('-', '_'); + component = this[bundle_component]; + } + + bundle.schemas.forEach(key => { + let property_name = this.get_property_name(key.name); + component[property_name + '_reset'](); + }); + }); + + this.emit('reset', true); + } + + /// From the gschema name, returns the name of the associated property on + /// the Prefs object. + get_property_name(name) { + return name.replaceAll('-', '_').toUpperCase(); + } + + /// Remove all connections managed by the Prefs object, i.e. created with + /// `prefs.PROPERTY_changed(callback)`. + disconnect_all_settings() { + this.keys.forEach(bundle => { + let component = this; + if (bundle.component !== "general") { + let bundle_component = bundle.component.replaceAll('-', '_'); + component = this[bundle_component]; + } + + bundle.schemas.forEach(key => { + let property_name = this.get_property_name(key.name); + component[property_name + '_disconnect'](); + }); + }); + } +}; + +Signals.addSignalMethods(Prefs.prototype); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/client.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/client.js new file mode 100644 index 0000000..1aae9bb --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/client.js @@ -0,0 +1,60 @@ +'use strict'; + +const Gio = imports.gi.Gio; + +const bus_name = 'org.gnome.Shell'; +const iface_name = 'dev.aunetx.BlurMyShell'; +const obj_path = '/dev/aunetx/BlurMyShell'; + + +/// Call pick() from the DBus service, it will open the Inspector from +/// gnome-shell to pick an actor on stage. +function pick() { + Gio.DBus.session.call( + bus_name, + obj_path, + iface_name, + 'pick', + null, + null, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + null, + null + ); +} + +/// Connect to DBus 'picking' signal, which will be emitted when the inspector +/// is picking a window. +function on_picking(cb) { + const id = Gio.DBus.session.signal_subscribe( + bus_name, + iface_name, + 'picking', + obj_path, + null, + Gio.DBusSignalFlags.NONE, + _ => { + cb(); + Gio.DBus.session.signal_unsubscribe(id); + } + ); +} + +/// Connect to DBus 'picked' signal, which will be emitted when a window is +/// picked. +function on_picked(cb) { + const id = Gio.DBus.session.signal_subscribe( + bus_name, + iface_name, + 'picked', + obj_path, + null, + Gio.DBusSignalFlags.NONE, + (conn, sender, obj_path, iface, signal, params) => { + const val = params.get_child_value(0); + cb(val.get_string()[0]); + Gio.DBus.session.signal_unsubscribe(id); + } + ); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/iface.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/iface.xml new file mode 100644 index 0000000..4f298ad --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/iface.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/services.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/services.js new file mode 100644 index 0000000..bfd7e3b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/dbus/services.js @@ -0,0 +1,93 @@ +'use strict'; + +const { Gio, GLib } = imports.gi; +const Main = imports.ui.main; +const LookingGlass = imports.ui.lookingGlass; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); + +const load_file = path => { + const [, buffer] = GLib.file_get_contents(path); + const contents = imports.byteArray.toString(buffer); + GLib.free(buffer); + return contents; +}; + +const iface = load_file(Me.dir.get_path() + '/dbus/iface.xml'); + +var ApplicationsService = class ApplicationsService { + constructor() { + this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(iface, this); + } + + /// Pick Window for Preferences Page, exported to DBus client. + pick() { + // emit `picking` signal to know we are listening + const send_picking_signal = _ => + this.DBusImpl.emit_signal( + 'picking', + null + ); + + // emit `picked` signal to send wm_class + const send_picked_signal = wm_class => + this.DBusImpl.emit_signal( + 'picked', + new GLib.Variant('(s)', [wm_class]) + ); + + // notify the preferences that we are listening + send_picking_signal(); + + // A very interesting way to pick a window: + // 1. Open LookingGlass to mask all event handles of window + // 2. Use inspector to pick window, thats is also lookingGlass do + // 3. Close LookingGlass when done + // It will restore event handles of window + + // open then hide LookingGlass + const looking_class = Main.createLookingGlass(); + looking_class.open(); + looking_class.hide(); + + // inspect window now + const inspector = new LookingGlass.Inspector(Main.createLookingGlass()); + inspector.connect('target', (me, target, x, y) => { + // remove border effect when window is picked. + const effect_name = 'lookingGlass_RedBorderEffect'; + target + .get_effects() + .filter(e => e.toString().includes(effect_name)) + .forEach(e => target.remove_effect(e)); + + // get wm_class_instance property of window, then pass it to DBus + // client + const type_str = target.toString(); + + let actor = target; + if (type_str.includes('MetaSurfaceActor')) + actor = target.get_parent(); + + if (!actor.toString().includes('WindowActor')) + return send_picked_signal('window-not-found'); + + send_picked_signal( + actor.meta_window.get_wm_class() ?? 'window-not-found' + ); + }); + + // close LookingGlass when we're done + inspector.connect('closed', _ => looking_class.close()); + } + + export() { + this.DBusImpl.export( + Gio.DBus.session, + '/dev/aunetx/BlurMyShell' + ); + } + + unexport() { + this.DBusImpl.unexport(); + } +}; diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.glsl b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.glsl new file mode 100644 index 0000000..142b89b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.glsl @@ -0,0 +1,13 @@ +uniform sampler2D tex; +uniform float red; +uniform float green; +uniform float blue; +uniform float blend; + +void main() { + vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); + vec3 pix_color = c.xyz; + vec3 color = vec3(red, green, blue); + + cogl_color_out = vec4(mix(pix_color, color, blend), 1.); +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.js new file mode 100644 index 0000000..a550f90 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/color_effect.js @@ -0,0 +1,186 @@ +'use strict'; + +const { GLib, GObject, Gio, Clutter, Shell } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { Prefs } = Me.imports.conveniences.settings; +const { Keys } = Me.imports.conveniences.keys; + + +const SHADER_PATH = GLib.build_filenamev( + [Me.path, 'effects', 'color_effect.glsl'] +); + +const get_shader_source = _ => { + try { + return Shell.get_file_contents_utf8_sync(SHADER_PATH); + } catch (e) { + log(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`); + return null; + } +}; + +/// New Clutter Shader Effect that simply mixes a color in, the class applies +/// the GLSL shader programmed into vfunc_get_static_shader_source and applies +/// it to an Actor. +/// +/// Clutter Shader Source Code: +/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c +/// +/// GJS Doc: +/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect +var ColorEffect = new GObject.registerClass({ + GTypeName: "ColorEffect", + Properties: { + 'red': GObject.ParamSpec.double( + `red`, + `Red`, + `Red value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + 'green': GObject.ParamSpec.double( + `green`, + `Green`, + `Green value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + 'blue': GObject.ParamSpec.double( + `blue`, + `Blue`, + `Blue value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + 'blend': GObject.ParamSpec.double( + `blend`, + `Blend`, + `Amount of blending between the colors`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + } +}, class ColorShader extends Clutter.ShaderEffect { + _init(params) { + this._red = null; + this._green = null; + this._blue = null; + this._blend = null; + + this._static = true; + this._prefs = new Prefs(Keys); + + // initialize without color as a parameter + + let _color = params.color; + delete params.color; + + super._init(params); + + // set shader source + + this._source = get_shader_source(); + + if (this._source) + this.set_shader_source(this._source); + + // set shader color + + if (_color) + this.color = _color; + + this.update_enabled(); + } + + get red() { + return this._red; + } + + set red(value) { + if (this._red !== value) { + this._red = value; + + this.set_uniform_value('red', parseFloat(this._red - 1e-6)); + } + } + + get green() { + return this._green; + } + + set green(value) { + if (this._green !== value) { + this._green = value; + + this.set_uniform_value('green', parseFloat(this._green - 1e-6)); + } + } + + get blue() { + return this._blue; + } + + set blue(value) { + if (this._blue !== value) { + this._blue = value; + + this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); + } + } + + get blend() { + return this._blend; + } + + set blend(value) { + if (this._blend !== value) { + this._blend = value; + + this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); + } + this.update_enabled(); + } + + set color(rgba) { + let [r, g, b, a] = rgba; + this.red = r; + this.green = g; + this.blue = b; + this.blend = a; + } + + get color() { + return [this.red, this.green, this.blue, this.blend]; + } + + /// False set function, only cares about the color. Too hard to change. + set(params) { + this.color = params.color; + } + + update_enabled() { + this.set_enabled( + this.blend > 0 && + this._prefs.COLOR_AND_NOISE && + this._static + ); + } + + + vfunc_paint_target(paint_node = null, paint_context = null) { + this.set_uniform_value("tex", 0); + + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl new file mode 100644 index 0000000..9140f33 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl @@ -0,0 +1,18 @@ +uniform sampler2D tex; +uniform float noise; +uniform float lightness; + +float PHI = 1.61803398874989484820459; +float SEED = 24; + +float noise_gen(in vec2 xy) { + return fract(tan(distance(xy * PHI, xy) * SEED) * xy.x); +} + +void main() { + vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); + vec3 pix_color = c.xyz; + float blend = noise * (1. - noise_gen(gl_FragCoord.xy)); + + cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.); +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.js new file mode 100644 index 0000000..f795364 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/noise_effect.js @@ -0,0 +1,106 @@ +'use strict'; + +const { GLib, GObject, Gio, Clutter, Shell } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { Prefs } = Me.imports.conveniences.settings; +const { Keys } = Me.imports.conveniences.keys; + + +const SHADER_PATH = GLib.build_filenamev( + [Me.path, 'effects', 'noise_effect.glsl'] +); + +const get_shader_source = _ => { + try { + return Shell.get_file_contents_utf8_sync(SHADER_PATH); + } catch (e) { + log(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`); + return null; + } +}; + +var NoiseEffect = new GObject.registerClass({ + GTypeName: "NoiseEffect", + Properties: { + 'noise': GObject.ParamSpec.double( + `noise`, + `Noise`, + `Amount of noise integrated with the image`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + 'lightness': GObject.ParamSpec.double( + `lightness`, + `Lightness`, + `Lightness of the grey used for the noise`, + GObject.ParamFlags.READWRITE, + 0.0, 2.0, + 0.4, + ), + } +}, class NoiseShader extends Clutter.ShaderEffect { + _init(params) { + this._noise = null; + this._lightness = null; + + this._static = true; + this._prefs = new Prefs(Keys); + + super._init(params); + + // set shader source + this._source = get_shader_source(); + if (this._source) + this.set_shader_source(this._source); + + this.update_enabled(); + } + + get noise() { + return this._noise; + } + + set noise(value) { + if (this._noise !== value) { + this._noise = value; + + this.set_uniform_value('noise', parseFloat(this._noise - 1e-6)); + } + this.update_enabled(); + } + + get lightness() { + return this._lightness; + } + + set lightness(value) { + if (this._lightness !== value) { + this._lightness = value; + + this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6)); + } + } + + update_enabled() { + this.set_enabled( + this.noise > 0 && + this._prefs.COLOR_AND_NOISE && + this._static + ); + } + + + vfunc_paint_target(paint_node = null, paint_context = null) { + this.set_uniform_value("tex", 0); + + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/paint_signals.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/paint_signals.js new file mode 100644 index 0000000..8c836fd --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/effects/paint_signals.js @@ -0,0 +1,90 @@ +'use strict'; + +const { GObject, Clutter } = imports.gi; + + +var PaintSignals = class PaintSignals { + constructor(connections) { + this.buffer = []; + this.connections = connections; + } + + connect(actor, blur_effect) { + let paint_effect = new EmitPaintSignal(); + let infos = { + actor: actor, + paint_effect: paint_effect + }; + let counter = 0; + + actor.add_effect(paint_effect); + this.connections.connect(paint_effect, 'update-blur', () => { + try { + // checking if blur_effect.queue_repaint() has been recently called + if (counter === 0) { + counter = 2; + blur_effect.queue_repaint(); + } + else counter--; + } catch (e) { } + }); + + // remove the actor from buffer when it is destroyed + if ( + actor.connect && + ( + !(actor instanceof GObject.Object) || + GObject.signal_lookup('destroy', actor) + ) + ) + this.connections.connect(actor, 'destroy', () => { + this.buffer.forEach(infos => { + if (infos.actor === actor) { + // remove from buffer + let index = this.buffer.indexOf(infos); + this.buffer.splice(index, 1); + } + }); + }); + + this.buffer.push(infos); + } + + disconnect_all_for_actor(actor) { + this.buffer.forEach(infos => { + if (infos.actor === actor) { + this.connections.disconnect_all_for(infos.paint_effect); + infos.actor.remove_effect(infos.paint_effect); + + // remove from buffer + let index = this.buffer.indexOf(infos); + this.buffer.splice(index, 1); + } + }); + } + + disconnect_all() { + this.buffer.forEach(infos => { + this.connections.disconnect_all_for(infos.paint_effect); + infos.actor.remove_effect(infos.paint_effect); + }); + + this.buffer = []; + } +}; + +var EmitPaintSignal = GObject.registerClass({ + GTypeName: 'EmitPaintSignal', + Signals: { + 'update-blur': { + param_types: [] + }, + } +}, + class EmitPaintSignal extends Clutter.Effect { + vfunc_paint(node, paint_context, paint_flags) { + this.emit("update-blur"); + super.vfunc_paint(node, paint_context, paint_flags); + } + } +); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/extension.js new file mode 100644 index 0000000..d8de89e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/extension.js @@ -0,0 +1,642 @@ +'use strict'; + +const { St, Shell, Gio, Gtk, Meta, Clutter } = imports.gi; +const Main = imports.ui.main; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); + +const { Connections } = Me.imports.conveniences.connections; +const { Prefs } = Me.imports.conveniences.settings; +const { Keys } = Me.imports.conveniences.keys; + +const Panel = Me.imports.components.panel; +const Overview = Me.imports.components.overview; +const DashToDock = Me.imports.components.dash_to_dock; +const Lockscreen = Me.imports.components.lockscreen; +const AppFolders = Me.imports.components.appfolders; +const WindowList = Me.imports.components.window_list; +const Applications = Me.imports.components.applications; +const Screenshot = Me.imports.components.screenshot; + +// This lists the components that need to be connected in order to either use +// general sigma/brightness or their own. +const INDEPENDENT_COMPONENTS = [ + "overview", "appfolder", "panel", "dash_to_dock", "applications", + "lockscreen", "window_list", "screenshot" +]; + + +/// The main extension class, created when the GNOME Shell is loaded. +class Extension { + constructor() { } + + /// 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 + + global.blur_my_shell = this; + + // create a Prefs instance, to manage extension's preferences + // it needs to be loaded before logging, as it checks for DEBUG + + this._prefs = new Prefs(Keys); + + this._log("enabling extension..."); + + // create main extension Connections instance + + this._connection = new Connections; + + // store it in a global array + + this._connections = [this._connection]; + + // create an instance of each component, with its associated Connections + + let init = _ => { + // create a Connections instance, to manage signals + let connection = new Connections; + + // store it to keeps track of them globally + this._connections.push(connection); + + return [connection, this._prefs]; + }; + + this._panel_blur = new Panel.PanelBlur(...init()); + this._dash_to_dock_blur = new DashToDock.DashBlur(...init()); + this._overview_blur = new Overview.OverviewBlur(...init()); + this._lockscreen_blur = new Lockscreen.LockscreenBlur(...init()); + this._appfolder_blur = new AppFolders.AppFoldersBlur(...init()); + this._window_list_blur = new WindowList.WindowListBlur(...init()); + this._applications_blur = new Applications.ApplicationsBlur(...init()); + this._screenshot_blur = new Screenshot.ScreenshotBlur(...init()); + + // maybe disable clipped redraw + + this._update_clipped_redraws(); + + // connect each component to preferences change + + this._connect_to_settings(); + + // 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 + if (Main.layoutManager._startingUp) { + this._connection.connect( + Main.layoutManager, + 'startup-complete', + this._enable_components.bind(this) + ); + } else { + this._enable_components(); + } + + // try to enable the components as soon as possible anyway, this way the + // overview may load before the user sees it + try { + if (this._prefs.overview.BLUR && !this._overview_blur.enabled) + this._overview_blur.enable(); + } catch (e) { } + try { + if (this._prefs.dash_to_dock.BLUR + && !this._dash_to_dock_blur.enabled) + this._dash_to_dock_blur.enable(); + } catch (e) { } + try { + if (this._prefs.panel.BLUR && !this._panel_blur.enabled) + this._panel_blur.enable(); + } catch (e) { } + } + + /// Disables the extension + disable() { + this._log("disabling extension..."); + + // disable every component + + this._panel_blur.disable(); + this._dash_to_dock_blur.disable(); + this._overview_blur.disable(); + 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._window_list_blur = null; + this._applications_blur = null; + + // make sure no settings change can re-enable them + + this._prefs.disconnect_all_settings(); + + // force disconnecting every signal, even if component crashed + + this._connections.forEach((connections) => { + connections.disconnect_all(); + }); + this._connections = []; + + // remove the clipped redraws flag + + this._reenable_clipped_redraws(); + + // remove the extension from GJS's global + + delete global.blur_my_shell; + + this._log("extension disabled."); + + this._prefs = null; + } + + /// Restart the extension. + _restart() { + this._log("restarting..."); + + this.disable(); + this.enable(); + + this._log("restarted."); + } + + /// 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 + /// boost for the compositor. + _update_clipped_redraws() { + if (this._prefs.HACKS_LEVEL === 3) + this._disable_clipped_redraws(); + else + this._reenable_clipped_redraws(); + } + + /// Add the Clutter debug flag. + _disable_clipped_redraws() { + Meta.add_clutter_debug_flags( + null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null + ); + } + + /// Remove the Clutter debug flag. + _reenable_clipped_redraws() { + Meta.remove_clutter_debug_flags( + null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null + ); + } + + /// Enables every component 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 + + if (this._prefs.panel.BLUR && !this._panel_blur.enabled) + this._panel_blur.enable(); + + if (this._prefs.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled) + this._dash_to_dock_blur.enable(); + + if (this._prefs.overview.BLUR && !this._overview_blur.enabled) + this._overview_blur.enable(); + + if (this._prefs.lockscreen.BLUR) + this._lockscreen_blur.enable(); + + if (this._prefs.appfolder.BLUR) + this._appfolder_blur.enable(); + + if (this._prefs.applications.BLUR) + this._applications_blur.enable(); + + if (this._prefs.window_list.BLUR) + this._window_list_blur.enable(); + + if (this._prefs.screenshot.BLUR) + this._screenshot_blur.enable(); + + this._log("all components enabled."); + } + + /// Updates needed things in each component when a preference changed + _connect_to_settings() { + + // global blur values changed, update everybody + + this._prefs.SIGMA_changed(() => { + this._update_sigma(); + }); + this._prefs.BRIGHTNESS_changed(() => { + this._update_brightness(); + }); + this._prefs.COLOR_changed(() => { + this._update_color(); + }); + this._prefs.NOISE_AMOUNT_changed(() => { + this._update_noise_amount(); + }); + this._prefs.NOISE_LIGHTNESS_changed(() => { + this._update_noise_lightness(); + }); + this._prefs.COLOR_AND_NOISE_changed(() => { + // both updating noise amount and color calls `update_enabled` on + // each color and noise effects + this._update_noise_amount(); + this._update_color(); + }); + + // restart the extension when hacks level is changed, easier than + // restarting individual components and should not happen often either + this._prefs.HACKS_LEVEL_changed(_ => this._restart()); + + // connect each component to use the proper sigma/brightness/color + + INDEPENDENT_COMPONENTS.forEach(component => { + this._connect_to_individual_settings(component); + }); + + // other component's preferences changed + + // ---------- OVERVIEW ---------- + + // toggled on/off + this._prefs.overview.BLUR_changed(() => { + if (this._prefs.overview.BLUR) { + this._overview_blur.enable(); + } else { + this._overview_blur.disable(); + } + }); + + // overview components style changed + this._prefs.overview.STYLE_COMPONENTS_changed(() => { + if (this._prefs.overview.BLUR) { + this._overview_blur.update_components_classname(); + } + }); + + + // ---------- APPFOLDER ---------- + + // toggled on/off + this._prefs.appfolder.BLUR_changed(() => { + if (this._prefs.appfolder.BLUR) { + this._appfolder_blur.enable(); + } else { + this._appfolder_blur.disable(); + } + }); + + // appfolder dialogs style changed + this._prefs.appfolder.STYLE_DIALOGS_changed(() => { + if (this._prefs.appfolder.BLUR) + this._appfolder_blur.blur_appfolders(); + }); + + + // ---------- PANEL ---------- + + // toggled on/off + this._prefs.panel.BLUR_changed(() => { + if (this._prefs.panel.BLUR) { + this._panel_blur.enable(); + } else { + this._panel_blur.disable(); + } + }); + + this._prefs.COLOR_AND_NOISE_changed(() => { + // permits making sure that the blur is not washed out when disabling + // the other effects + if (this._prefs.panel.BLUR) + this._panel_blur.invalidate_all_blur(); + }); + + // static blur toggled on/off + this._prefs.panel.STATIC_BLUR_changed(() => { + if (this._prefs.panel.BLUR) + this._panel_blur.update_all_blur_type(); + }); + + // panel blur's overview connection toggled on/off + this._prefs.panel.UNBLUR_IN_OVERVIEW_changed(() => { + this._panel_blur.connect_to_windows_and_overview(); + }); + + // panel override background toggled on/off + this._prefs.panel.OVERRIDE_BACKGROUND_changed(() => { + if (this._prefs.panel.BLUR) + this._panel_blur.connect_to_windows_and_overview(); + }); + + // panel style changed + this._prefs.panel.STYLE_PANEL_changed(() => { + if (this._prefs.panel.BLUR) + this._panel_blur.connect_to_windows_and_overview(); + }); + + // panel background's dynamic overriding toggled on/off + this._prefs.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => { + if (this._prefs.panel.BLUR) + this._panel_blur.connect_to_windows_and_overview(); + }); + + + // ---------- DASH TO DOCK ---------- + + // toggled on/off + this._prefs.dash_to_dock.BLUR_changed(() => { + if (this._prefs.dash_to_dock.BLUR) { + this._dash_to_dock_blur.enable(); + } else { + this._dash_to_dock_blur.disable(); + } + }); + + // TODO implement static blur for dash + // static blur toggled on/off + this._prefs.dash_to_dock.STATIC_BLUR_changed(() => { + //if (this._prefs.dash_to_dock.BLUR) + // this._dash_to_dock_blur.change_blur_type(); + }); + + // dash-to-dock override background toggled on/off + this._prefs.dash_to_dock.OVERRIDE_BACKGROUND_changed(() => { + if (this._prefs.dash_to_dock.BLUR) + this._dash_to_dock_blur.update_background(); + }); + + // dash-to-dock style changed + this._prefs.dash_to_dock.STYLE_DASH_TO_DOCK_changed(() => { + if (this._prefs.dash_to_dock.BLUR) + this._dash_to_dock_blur.update_background(); + }); + + // dash-to-dock blur's overview connection toggled on/off + this._prefs.dash_to_dock.UNBLUR_IN_OVERVIEW_changed(() => { + if (this._prefs.dash_to_dock.BLUR) + this._dash_to_dock_blur.connect_to_overview(); + }); + + + // ---------- APPLICATIONS ---------- + + // toggled on/off + this._prefs.applications.BLUR_changed(() => { + if (this._prefs.applications.BLUR) { + this._applications_blur.enable(); + } else { + this._applications_blur.disable(); + } + }); + + // application opacity changed + this._prefs.applications.OPACITY_changed(_ => { + if (this._prefs.applications.BLUR) + this._applications_blur.set_opacity( + this._prefs.applications.OPACITY + ); + }); + + // application blur-on-overview changed + this._prefs.applications.BLUR_ON_OVERVIEW_changed(_ => { + if (this._prefs.applications.BLUR) + this._applications_blur.connect_to_overview(); + }); + + // application enable-all changed + this._prefs.applications.ENABLE_ALL_changed(_ => { + if (this._prefs.applications.BLUR) + this._applications_blur.update_all_windows(); + }); + + // application whitelist changed + this._prefs.applications.WHITELIST_changed(_ => { + if ( + this._prefs.applications.BLUR + && !this._prefs.applications.ENABLE_ALL + ) + this._applications_blur.update_all_windows(); + }); + + // application blacklist changed + this._prefs.applications.BLACKLIST_changed(_ => { + if ( + this._prefs.applications.BLUR + && this._prefs.applications.ENABLE_ALL + ) + this._applications_blur.update_all_windows(); + }); + + + // ---------- LOCKSCREEN ---------- + + // toggled on/off + this._prefs.lockscreen.BLUR_changed(() => { + if (this._prefs.lockscreen.BLUR) { + this._lockscreen_blur.enable(); + } else { + this._lockscreen_blur.disable(); + } + }); + + + // ---------- WINDOW LIST ---------- + + // toggled on/off + this._prefs.window_list.BLUR_changed(() => { + if (this._prefs.window_list.BLUR) { + this._window_list_blur.enable(); + } else { + this._window_list_blur.disable(); + } + }); + + + // ---------- HIDETOPBAR ---------- + + // toggled on/off + this._prefs.hidetopbar.COMPATIBILITY_changed(() => { + // no need to verify if it is enabled or not, it is done anyway + this._panel_blur.connect_to_windows_and_overview(); + }); + + + // ---------- SCREENSHOT ---------- + + // toggled on/off + this._prefs.screenshot.BLUR_changed(() => { + if (this._prefs.screenshot.BLUR) { + this._screenshot_blur.enable(); + } else { + this._screenshot_blur.disable(); + } + }); + } + + /// Select the component by its name and connect it to its preferences + /// changes for general values, sigma and brightness. + /// + /// Doing this in such a way is less accessible but prevents a lot of + /// boilerplate and headaches. + _connect_to_individual_settings(name) { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // general values switch is toggled + component_prefs.CUSTOMIZE_changed(() => { + if (component_prefs.CUSTOMIZE) { + component.set_sigma(component_prefs.SIGMA); + component.set_brightness(component_prefs.BRIGHTNESS); + component.set_color(component_prefs.COLOR); + component.set_noise_amount(component_prefs.NOISE_AMOUNT); + component.set_noise_lightness(component_prefs.NOISE_LIGHTNESS); + } + else { + component.set_sigma(this._prefs.SIGMA); + component.set_brightness(this._prefs.BRIGHTNESS); + component.set_color(this._prefs.COLOR); + component.set_noise_amount(this._prefs.NOISE_AMOUNT); + component.set_noise_lightness(this._prefs.NOISE_LIGHTNESS); + } + }); + + // sigma is changed + component_prefs.SIGMA_changed(() => { + if (component_prefs.CUSTOMIZE) + component.set_sigma(component_prefs.SIGMA); + else + component.set_sigma(this._prefs.SIGMA); + }); + + // brightness is changed + component_prefs.BRIGHTNESS_changed(() => { + if (component_prefs.CUSTOMIZE) + component.set_brightness(component_prefs.BRIGHTNESS); + else + component.set_brightness(this._prefs.BRIGHTNESS); + }); + + // color is changed + component_prefs.COLOR_changed(() => { + if (component_prefs.CUSTOMIZE) + component.set_color(component_prefs.COLOR); + else + component.set_color(this._prefs.COLOR); + }); + + // noise amount is changed + component_prefs.NOISE_AMOUNT_changed(() => { + if (component_prefs.CUSTOMIZE) + component.set_noise_amount(component_prefs.NOISE_AMOUNT); + else + component.set_noise_amount(this._prefs.NOISE_AMOUNT); + }); + + // noise lightness is changed + component_prefs.NOISE_LIGHTNESS_changed(() => { + if (component_prefs.CUSTOMIZE) + component.set_noise_lightness(component_prefs.NOISE_LIGHTNESS); + else + component.set_noise_lightness(this._prefs.NOISE_LIGHTNESS); + }); + } + + /// Update each component's sigma value + _update_sigma() { + INDEPENDENT_COMPONENTS.forEach(name => { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // update sigma accordingly + if (component_prefs.CUSTOMIZE) { + component.set_sigma(component_prefs.SIGMA); + } + else { + component.set_sigma(this._prefs.SIGMA); + } + }); + } + + /// Update each component's brightness value + _update_brightness() { + INDEPENDENT_COMPONENTS.forEach(name => { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // update brightness accordingly + if (component_prefs.CUSTOMIZE) + component.set_brightness(component_prefs.BRIGHTNESS); + else + component.set_brightness(this._prefs.BRIGHTNESS); + }); + } + + /// Update each component's color value + _update_color() { + INDEPENDENT_COMPONENTS.forEach(name => { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // update color accordingly + if (component_prefs.CUSTOMIZE) + component.set_color(component_prefs.COLOR); + else + component.set_color(this._prefs.COLOR); + }); + } + + /// Update each component's noise amount value + _update_noise_amount() { + INDEPENDENT_COMPONENTS.forEach(name => { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // update color accordingly + if (component_prefs.CUSTOMIZE) + component.set_noise_amount(component_prefs.NOISE_AMOUNT); + else + component.set_noise_amount(this._prefs.NOISE_AMOUNT); + }); + } + + /// Update each component's noise lightness value + _update_noise_lightness() { + INDEPENDENT_COMPONENTS.forEach(name => { + // get component and preferences needed + let component = this['_' + name + '_blur']; + let component_prefs = this._prefs[name]; + + // update color accordingly + if (component_prefs.CUSTOMIZE) + component.set_noise_lightness(component_prefs.NOISE_LIGHTNESS); + else + component.set_noise_lightness(this._prefs.NOISE_LIGHTNESS); + }); + } + + _log(str) { + if (this._prefs.DEBUG) + log(`[Blur my Shell > extension] ${str}`); + } +} + + +// Called on gnome-shell loading, even if extension is deactivated +function init() { + return new Extension(); +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg new file mode 100644 index 0000000..bdab309 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg new file mode 100644 index 0000000..87f307f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg new file mode 100644 index 0000000..2eda98b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg new file mode 100644 index 0000000..5a78b46 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg new file mode 100644 index 0000000..e11da07 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg new file mode 100644 index 0000000..8378c9c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg @@ -0,0 +1,40 @@ + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg new file mode 100644 index 0000000..45e703e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg new file mode 100644 index 0000000..445f662 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg new file mode 100644 index 0000000..a8da14f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg new file mode 100644 index 0000000..e443de4 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg new file mode 100644 index 0000000..cad2da8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg new file mode 100644 index 0000000..cad2da8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..b20cc9a Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..dc55bc6 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..00b61a7 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..0e10fb0 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..0c817b7 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..76cf64a Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..21b14fe Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..6d7fc9f Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..c58b4c0 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..994eba3 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..2db8df9 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..0d784a1 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..04fa332 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..258596c Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..0ffba15 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..bd7437c Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000..2066d0e Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/metadata.json new file mode 100644 index 0000000..735e506 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/metadata.json @@ -0,0 +1,16 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Adds a blur look to different parts of the GNOME Shell, including the top panel, dash and overview.\n\nYou can support my work by sponsoring me on:\n- github: https://github.com/sponsors/aunetx\n- ko-fi: https://ko-fi.com/aunetx\n\nNote: if the extension shows an error after updating, please make sure to restart your session to see if it persists. This is due to a bug in gnome shell, which I can't fix by myself.", + "name": "Blur my Shell", + "original-authors": [ + "me@aunetx.dev" + ], + "settings-schema": "org.gnome.shell.extensions.blur-my-shell", + "shell-version": [ + "42", + "43" + ], + "url": "https://github.com/aunetx/gnome-shell-extension-blur-my-shell", + "uuid": "blur-my-shell@aunetx", + "version": 44 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/applications.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/applications.js new file mode 100644 index 0000000..9c01297 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/applications.js @@ -0,0 +1,175 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { WindowRow } = Me.imports.preferences.window_row; + + +const make_array = prefs_group => { + let list_box = prefs_group + .get_first_child() + .get_last_child() + .get_first_child(); + + let elements = []; + let i = 0; + let element = list_box.get_row_at_index(i); + while (element) { + elements.push(element); + i++; + element = list_box.get_row_at_index(i); + } + + return elements; +}; + + +var Applications = GObject.registerClass({ + GTypeName: 'Applications', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'applications.ui'])}`, + InternalChildren: [ + 'blur', + 'customize', + 'opacity', + 'blur_on_overview', + 'enable_all', + 'whitelist', + 'add_window_whitelist', + 'blacklist', + 'add_window_blacklist' + ], +}, class Applications extends Adw.PreferencesPage { + constructor(preferences, preferences_window) { + super({}); + this._preferences_window = preferences_window; + + this.preferences = preferences; + + this.preferences.applications.settings.bind( + 'blur', this._blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.applications.settings.bind( + 'opacity', this._opacity, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.applications.settings.bind( + 'blur-on-overview', this._blur_on_overview, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.applications.settings.bind( + 'enable-all', this._enable_all, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._customize.connect_to(this.preferences.applications, false); + + // connect 'enable all' button to whitelist/blacklist visibility + this._enable_all.bind_property( + 'active', this._whitelist, 'visible', + GObject.BindingFlags.INVERT_BOOLEAN + ); + this._enable_all.bind_property( + 'active', this._blacklist, 'visible', + GObject.BindingFlags.DEFAULT + ); + + // make sure that blacklist / whitelist is correctly hidden + if (this._enable_all.active) + this._whitelist.visible = false; + this._blacklist.visible = !this._whitelist.visible; + + // listen to app row addition + this._add_window_whitelist.connect('clicked', + _ => this.add_to_whitelist() + ); + this._add_window_blacklist.connect('clicked', + _ => this.add_to_blacklist() + ); + + // add initial applications + this.add_widgets_from_lists(); + + this.preferences.connect('reset', _ => { + this.remove_all_widgets(); + this.add_widgets_from_lists(); + }); + } + + // A way to retriew the whitelist widgets. + get _whitelist_elements() { + return make_array(this._whitelist); + } + + // A way to retriew the blacklist widgets. + get _blacklist_elements() { + return make_array(this._blacklist); + } + + add_widgets_from_lists() { + this.preferences.applications.WHITELIST.forEach( + app_name => this.add_to_whitelist(app_name) + ); + + this.preferences.applications.BLACKLIST.forEach( + app_name => this.add_to_blacklist(app_name) + ); + + } + + close_all_expanded_rows() { + this._whitelist_elements.forEach( + element => element.set_expanded(false) + ); + this._blacklist_elements.forEach( + element => element.set_expanded(false) + ); + } + + remove_all_widgets() { + this._whitelist_elements.forEach( + element => this._whitelist.remove(element) + ); + this._blacklist_elements.forEach( + element => this._blacklist.remove(element) + ); + } + + add_to_whitelist(app_name = null) { + let window_row = new WindowRow('whitelist', this, app_name); + this._whitelist.add(window_row); + } + + add_to_blacklist(app_name = null) { + let window_row = new WindowRow('blacklist', this, app_name); + this._blacklist.add(window_row); + } + + update_whitelist_titles() { + let titles = this._whitelist_elements + .map(element => element._window_class.buffer.text) + .filter(title => title != ""); + + this.preferences.applications.WHITELIST = titles; + } + + update_blacklist_titles() { + let titles = this._blacklist_elements + .map(element => element._window_class.buffer.text) + .filter(title => title != ""); + + this.preferences.applications.BLACKLIST = titles; + } + + remove_from_whitelist(widget) { + this._whitelist.remove(widget); + this.update_whitelist_titles(); + } + + remove_from_blacklist(widget) { + this._blacklist.remove(widget); + this.update_blacklist_titles(); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/customize_row.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/customize_row.js new file mode 100644 index 0000000..f51fa43 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/customize_row.js @@ -0,0 +1,168 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio, Gtk } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { Prefs } = Me.imports.conveniences.settings; +const { Keys } = Me.imports.conveniences.keys; + + +/// Given a component (described by its preferences node), a gschema key and +/// a Gtk.ColorButton, binds everything transparently. +let bind_color = function (component, key, widget) { + let property_name = key.replaceAll('-', '_').toUpperCase(); + + let parse_color = _ => { + let [r, g, b, a] = component[property_name]; + let w = widget.rgba; + w.red = r; + w.green = g; + w.blue = b; + w.alpha = a; + widget.rgba = w; + }; + component.settings.connect('changed::' + key, parse_color); + + widget.connect('color-set', _ => { + let c = widget.rgba; + component[property_name] = [c.red, c.green, c.blue, c.alpha]; + }); + + parse_color(); +}; + +var CustomizeRow = GObject.registerClass({ + GTypeName: 'CustomizeRow', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'customize-row.ui'])}`, + InternalChildren: [ + 'sigma', + 'brightness', + 'color', + 'color_row', + 'noise_amount', + 'noise_amount_row', + 'noise_lightness', + 'noise_lightness_row', + 'noise_color_notice' + ], +}, class CustomizeRow extends Adw.ExpanderRow { + /// Makes the required connections between the widgets and the preferences. + /// + /// This function may be bound to another object than CustomizeRow, if we + /// are using it for the General page; some things will then change (no + /// expansion row, and no notice) + /// + /// The color_and_noise parameter is either a boolean (true by default) or + /// a widget; and permits selecting weather or not we want to show the color + /// and noise buttons to the user. If it is a widget, it means we need to + /// dynamically update their visibility, according to the widget's state. + connect_to(component_prefs, color_and_noise = true) { + let s = component_prefs.settings; + + // is not fired if in General page + if (this instanceof CustomizeRow) + // bind the customize button + s.bind( + 'customize', this, 'enable-expansion', + Gio.SettingsBindFlags.DEFAULT + ); + + // bind sigma and brightness + s.bind( + 'sigma', this._sigma, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + s.bind( + 'brightness', this._brightness, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // bind the color button + bind_color(component_prefs, 'color', this._color); + + // bind noise sliders + s.bind( + 'noise-amount', this._noise_amount, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + s.bind( + 'noise-lightness', this._noise_lightness, 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // color_and_noise is either a boolean or a widget, if true, or it is a + // widget, this will appropriately show the required preferences about + // setting the color and noise + if (color_and_noise) { + // if we gave the static_blur widget, we are dealing with the panel, + // and binding it to enable/disable the required components when + // switching between static and dynamic blur + if (color_and_noise instanceof Gtk.Switch) { + // bind its state to dynamically toggle the notice and rows + color_and_noise.bind_property( + 'state', this._color_row, 'visible', + GObject.BindingFlags.SYNC_CREATE + ); + color_and_noise.bind_property( + 'state', this._noise_amount_row, 'visible', + GObject.BindingFlags.SYNC_CREATE + ); + color_and_noise.bind_property( + 'state', this._noise_lightness_row, 'visible', + GObject.BindingFlags.SYNC_CREATE + ); + color_and_noise.bind_property( + 'state', this._noise_color_notice, 'visible', + GObject.BindingFlags.INVERT_BOOLEAN + ); + + // only way to get the correct state when first opening the + // window... + setTimeout(_ => { + let is_visible = color_and_noise.state; + this._color_row.visible = is_visible; + this._noise_amount_row.visible = is_visible; + this._noise_lightness_row.visible = is_visible; + this._noise_color_notice.visible = !is_visible; + }, 10); + } + + // if in General page, there is no notice at all + if (this instanceof CustomizeRow) { + // disable the notice + this._noise_color_notice.visible = false; + } + } else { + // enable the notice and disable color and noise preferences + this._color_row.visible = false; + this._noise_amount_row.visible = false; + this._noise_lightness_row.visible = false; + this._noise_color_notice.visible = true; + } + + const Preferences = new Prefs(Keys); + + // now we bind the color-and-noise preference to the sensitivity of the + // associated widgets, this will grey them out if the user choose not to + // have color and noise enabled + // note: I would love to bind to the visibility instead, but this part + // is already dirty enough, it would look like I obfuscate my code + // intentionally... (I am not) + Preferences.settings.bind( + 'color-and-noise', + this._color_row, 'sensitive', + Gio.SettingsBindFlags.DEFAULT + ); + Preferences.settings.bind( + 'color-and-noise', + this._noise_amount_row, 'sensitive', + Gio.SettingsBindFlags.DEFAULT + ); + Preferences.settings.bind( + 'color-and-noise', + this._noise_lightness_row, 'sensitive', + Gio.SettingsBindFlags.DEFAULT + ); + }; +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/dash.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/dash.js new file mode 100644 index 0000000..b00181b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/dash.js @@ -0,0 +1,45 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); + + +var Dash = GObject.registerClass({ + GTypeName: 'Dash', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'dash.ui'])}`, + InternalChildren: [ + 'blur', + 'customize', + 'override_background', + 'style_dash_to_dock', + 'unblur_in_overview' + ], +}, class Dash extends Adw.PreferencesPage { + constructor(preferences) { + super({}); + + this.preferences = preferences; + + this.preferences.dash_to_dock.settings.bind( + 'blur', this._blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.dash_to_dock.settings.bind( + 'override-background', + this._override_background, 'enable-expansion', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.dash_to_dock.settings.bind( + 'style-dash-to-dock', this._style_dash_to_dock, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.dash_to_dock.settings.bind( + 'unblur-in-overview', this._unblur_in_overview, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._customize.connect_to(this.preferences.dash_to_dock, false); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/general.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/general.js new file mode 100644 index 0000000..74f494a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/general.js @@ -0,0 +1,50 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { CustomizeRow } = Me.imports.preferences.customize_row; + + +var General = GObject.registerClass({ + GTypeName: 'General', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'general.ui'])}`, + InternalChildren: [ + 'sigma', + 'brightness', + 'color', + 'color_row', + 'noise_amount', + 'noise_amount_row', + 'noise_lightness', + 'noise_lightness_row', + 'color_and_noise', + 'hack_level', + 'debug', + 'reset' + ], +}, class General extends Adw.PreferencesPage { + constructor(preferences) { + super({}); + + this.preferences = preferences; + + CustomizeRow.prototype.connect_to.call(this, this.preferences); + + this.preferences.settings.bind( + 'color-and-noise', this._color_and_noise, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.settings.bind( + 'hacks-level', this._hack_level, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.settings.bind( + 'debug', this._debug, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._reset.connect('clicked', _ => this.preferences.reset()); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/menu.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/menu.js new file mode 100644 index 0000000..a319a2d --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/menu.js @@ -0,0 +1,64 @@ +'use strict'; + +const { Gdk, Gtk, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); + +function addMenu(window) { + const builder = new Gtk.Builder(); + + // add a dummy page and remove it immediately, to access headerbar + builder.add_from_file(`${Me.path}/ui/menu.ui`); + let menu_util = builder.get_object('menu_util'); + window.add(menu_util); + addMenuToHeader(window, builder); + window.remove(menu_util); +} + +function addMenuToHeader(window, builder) { + // a little hack to get to the headerbar + const page = builder.get_object('menu_util'); + const pages_stack = page.get_parent(); // AdwViewStack + const content_stack = pages_stack.get_parent().get_parent(); // GtkStack + const preferences = content_stack.get_parent(); // GtkBox + const headerbar = preferences.get_first_child(); // AdwHeaderBar + headerbar.pack_start(builder.get_object('info_menu')); + + // 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://github.com/aunetx/blur-my-shell/issues' + }, + { + name: 'open-readme', + link: 'https://github.com/aunetx/blur-my-shell' + }, + { + name: 'open-license', + link: 'https://github.com/aunetx/blur-my-shell/blob/master/LICENSE' + }, + { + name: 'donate-github', + link: 'https://github.com/sponsors/aunetx' + }, + { + name: 'donate-kofi', + link: 'https://ko-fi.com/aunetx' + }, + ]; + + 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); + }); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/other.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/other.js new file mode 100644 index 0000000..4ba3a88 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/other.js @@ -0,0 +1,51 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); + + +var Other = GObject.registerClass({ + GTypeName: 'Other', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'other.ui'])}`, + InternalChildren: [ + 'lockscreen_blur', + 'lockscreen_customize', + + 'screenshot_blur', + 'screenshot_customize', + + 'window_list_blur', + 'window_list_customize', + ], +}, class Overview extends Adw.PreferencesPage { + constructor(preferences) { + super({}); + + this.preferences = preferences; + + this.preferences.lockscreen.settings.bind( + 'blur', this._lockscreen_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._lockscreen_customize.connect_to(this.preferences.lockscreen); + + this.preferences.screenshot.settings.bind( + 'blur', this._screenshot_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._screenshot_customize.connect_to(this.preferences.screenshot); + + this.preferences.window_list.settings.bind( + 'blur', this._window_list_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._window_list_customize.connect_to( + this.preferences.window_list, false + ); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/overview.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/overview.js new file mode 100644 index 0000000..f60b61e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/overview.js @@ -0,0 +1,49 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); + + +var Overview = GObject.registerClass({ + GTypeName: 'Overview', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'overview.ui'])}`, + InternalChildren: [ + 'overview_blur', + 'overview_customize', + 'overview_style_components', + + 'appfolder_blur', + 'appfolder_customize', + 'appfolder_style_dialogs' + ], +}, class Overview extends Adw.PreferencesPage { + constructor(preferences) { + super({}); + + this.preferences = preferences; + + this.preferences.overview.settings.bind( + 'blur', this._overview_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.overview.settings.bind( + 'style-components', this._overview_style_components, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + + this._overview_customize.connect_to(this.preferences.overview); + + this.preferences.appfolder.settings.bind( + 'blur', this._appfolder_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.appfolder.settings.bind( + 'style-dialogs', this._appfolder_style_dialogs, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + + this._appfolder_customize.connect_to(this.preferences.appfolder, false); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/panel.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/panel.js new file mode 100644 index 0000000..e127feb --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/panel.js @@ -0,0 +1,62 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); + + +var Panel = GObject.registerClass({ + GTypeName: 'Panel', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'panel.ui'])}`, + InternalChildren: [ + 'blur', + 'customize', + 'static_blur', + 'unblur_in_overview', + 'override_background', + 'style_panel', + 'override_background_dynamically', + 'hidetopbar_compatibility' + ], +}, class Panel extends Adw.PreferencesPage { + constructor(preferences) { + super({}); + + this.preferences = preferences; + + this.preferences.panel.settings.bind( + 'blur', this._blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'static-blur', this._static_blur, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'unblur-in-overview', this._unblur_in_overview, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'override-background', + this._override_background, 'enable-expansion', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'style-panel', this._style_panel, 'selected', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.panel.settings.bind( + 'override-background-dynamically', + this._override_background_dynamically, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + + this._customize.connect_to(this.preferences.panel, this._static_blur); + + this.preferences.hidetopbar.settings.bind( + 'compatibility', this._hidetopbar_compatibility, 'state', + Gio.SettingsBindFlags.DEFAULT + ); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/window_row.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/window_row.js new file mode 100644 index 0000000..9415c8e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/preferences/window_row.js @@ -0,0 +1,108 @@ +'use strict'; + +const { Adw, GLib, GObject, Gio, Gtk } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { pick, on_picking, on_picked } = Me.imports.dbus.client; + + +var WindowRow = GObject.registerClass({ + GTypeName: 'WindowRow', + Template: `file://${GLib.build_filenamev([Me.path, 'ui', 'window-row.ui'])}`, + InternalChildren: [ + 'window_picker', + 'window_class', + 'picking_failure_toast' + ], +}, class WindowRow extends Adw.ExpanderRow { + constructor(list, app_page, app_name) { + super({}); + this._list = list; + this._app_page = app_page; + + // add a 'remove' button before the text + let action_row = this.child.get_first_child().get_first_child(); + let remove_button = new Gtk.Button({ + 'icon-name': 'remove-window-symbolic', + 'width-request': 38, + 'height-request': 38, + 'margin-top': 6, + 'margin-bottom': 6, + }); + remove_button.add_css_class('circular'); + remove_button.add_css_class('flat'); + action_row.add_prefix(remove_button); + + // connect the button to the whitelist / blacklist removal + remove_button.connect('clicked', _ => this._remove_row()); + + // bind row title to text buffer + this._window_class.buffer.bind_property( + 'text', this, 'title', + Gio.SettingsBindFlags.BIDIRECTIONNAL + ); + + // set application name if it exists, or open the revealer and pick one + if (app_name) + this._window_class.buffer.text = app_name; + else { + app_page.close_all_expanded_rows(); + this.set_expanded(true); + this._do_pick_window(true); + } + + // pick a window when the picker button is clicked + this._window_picker.connect('clicked', _ => this._do_pick_window()); + + // update list on text buffer change + this._window_class.connect('changed', + _ => this._update_rows_titles() + ); + } + + _remove_row() { + this._app_page["remove_from_" + this._list](this); + } + + _update_rows_titles() { + this._app_page["update_" + this._list + "_titles"](this); + } + + _do_pick_window(remove_if_failed = false) { + // a mechanism to know if the extension is listening correcly + let has_responded = false; + let should_take_answer = true; + setTimeout(_ => { + if (!has_responded) { + // show toast about failure + this._app_page._preferences_window.add_toast( + this._picking_failure_toast + ); + + // prevent title from changing with later picks + should_take_answer = false; + + // remove row if asked + if (remove_if_failed) + this._remove_row(); + } + }, 15); + + on_picking(_ => + has_responded = true + ); + + on_picked(wm_class => { + if (should_take_answer) { + if (wm_class == 'window-not-found') { + log("Can't pick window from here"); + return; + } + this._window_class.buffer.text = wm_class; + } + }); + + pick(); + } +}); diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/prefs.js new file mode 100644 index 0000000..10dc080 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/prefs.js @@ -0,0 +1,43 @@ +'use strict'; + +const { Adw, Gdk, GLib, Gtk, GObject, Gio } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const { Prefs } = Me.imports.conveniences.settings; +const { Keys } = Me.imports.conveniences.keys; + +const { addMenu } = Me.imports.preferences.menu; +const { CustomizeRow } = Me.imports.preferences.customize_row; +const { WindowRow } = Me.imports.preferences.window_row; +const { General } = Me.imports.preferences.general; +const { Panel } = Me.imports.preferences.panel; +const { Overview } = Me.imports.preferences.overview; +const { Dash } = Me.imports.preferences.dash; +const { Applications } = Me.imports.preferences.applications; +const { Other } = Me.imports.preferences.other; + + +function init() { + ExtensionUtils.initTranslations(Me.metadata.uuid); + + // load the icon theme + let iconPath = Me.dir.get_child("icons").get_path(); + let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); + iconTheme.add_search_path(iconPath); +} + +function fillPreferencesWindow(window) { + addMenu(window); + + const preferences = new Prefs(Keys); + + window.add(new General(preferences)); + window.add(new Panel(preferences)); + window.add(new Overview(preferences)); + window.add(new Dash(preferences)); + window.add(new Applications(preferences, window)); + window.add(new Other(preferences)); + + window.search_enabled = true; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled new file mode 100644 index 0000000..7f7ba21 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml new file mode 100644 index 0000000..5d326d6 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml @@ -0,0 +1,457 @@ + + + + + + + 30 + Global sigma (gaussian blur radius) to use + + + + 0.6 + Global brightness to use + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + true + Boolean, controls wether or not the color and noise effects are in use globally + + + + 1 + Level of hacks to use (from 0 to 3, 3 disabling clipped redraws entirely) + + + + false + Boolean, set to true to activate debug mode (more verbose journalctl logs) + + + + + + + + + + + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + 1 + Enum to select the style of the components in overview (0 not styled, 1 light, 2 dark, 3 transparent) + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + 1 + Enum to select the style of the appfolder dialogs (0 not styled, 1 transparent, 2 light, 3 dark) + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + true + Boolean, whether to use a static or dynamic blur for this component + + + + true + Boolean, whether to disable blur from this component when opening the overview or not + + + + true + Boolean, whether to override the background or not + + + + 0 + Enum to select the style of the panel (0 transparent, 1 light, 2 dark) + + + + false + Boolean, whether to disable blur from this component when a window is close to the panel + + + + + + + + false + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + true + Boolean, whether to use static or dynamic blur for this component + + + + true + Boolean, whether to override the background or not + + + + 1 + Enum to select the style of dash to dock (0 transparent, 1 light, 2 dark) + + + + false + Boolean, whether to disable blur from this component when opening the overview or not + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + true + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 1. + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + 230 + Opacity of the window actor on top of the blur effect + + + + false + Wether or not to blur applications on the overview + + + + false + Wether or not to blur all applications by default + + + + [] + List of applications to blur + + + + ["Plank"] + List of applications not to blur + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + + + + + true + Boolean, whether to blur activate the blur for this component or not + + + + false + Boolean, whether to customize the blur effect sigma/brightness or use general values + + + + 30 + Sigma (gaussian blur radius) to use for the blur effect + + + + 0.6 + Brightness to use for the blur effect + + + + (0.,0.,0.,0.) + Color to mix with the blur effect + + + + 0. + Amount of noise to add to the blur effect + + + + 0. + Lightness of the noise added to the blur effect + + + + + + + + false + Boolean, whether to try compatibility with hidetopbar@mathieu.bidon.ca or not + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/stylesheet.css new file mode 100644 index 0000000..dbe5f37 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/stylesheet.css @@ -0,0 +1,257 @@ +/*** PANEL ***/ + +/* +* `.transparent-panel` +*/ +#panel.transparent-panel { + background: transparent; + transition-duration: 500ms; +} + +/* +* `.dark-panel` +*/ +#panel.dark-panel { + background-color: rgba(100, 100, 100, 0.35); + transition-duration: 500ms; +} + +/* +* `.light-panel` +*/ +#panel.light-panel { + background-color: rgba(200, 200, 200, 0.2); + transition-duration: 500ms; +} + + +/*** DASH ***/ + +/* +* `.transparent-dash` +*/ +.transparent-dash .dash-background { + background-color: transparent !important; +} + +/* +* `.light-dash` +*/ +.light-dash .dash-background { + background-color: rgba(200, 200, 200, 0.2) !important; +} + +/* +* `.dark-dash` +*/ +.dark-dash .dash-background { + background-color: rgba(100, 100, 100, 0.35) !important; +} + + +/*** OVERVIEW ***/ + +/* +* Add transparency to the workspace animation (between workspaces) +*/ +.blurred-overview .workspace-animation { + background-color: transparent !important; +} + + +/* +* `.overview-components-transparent` +*/ + +.overview-components-transparent .search-entry { + color: white; + background-color: rgba(0, 0, 0, 0); + border-color: transparent; + box-shadow: none; +} + +.overview-components-transparent .search-entry .search-entry-icon { + color: rgba(255, 255, 255, 0.65); +} + +.overview-components-transparent .search-section-content, +.overview-components-transparent .app-folder .overview-icon { + background-color: rgba(0, 0, 0, 0); +} + +/* prevents the extension from interfering with Just Perfection */ +.overview-components-transparent.just-perfection .search-section-content { + 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); +} + +/* 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-light` +*/ + +.overview-components-light .search-entry { + color: white; + background-color: rgba(200, 200, 200, 0.2); + border-color: transparent; + box-shadow: none; +} + +.overview-components-light .search-entry .search-entry-icon { + color: rgba(255, 255, 255, 0.65); +} + +.overview-components-light .search-section-content, +.overview-components-light .app-folder .overview-icon { + background-color: rgba(200, 200, 200, 0.2); +} + +/* prevents the extension from interfering with Just Perfection */ +.overview-components-light.just-perfection .search-section-content { + 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); +} + +/* 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-dark` +*/ + +.overview-components-dark .search-entry { + color: white; + background-color: rgba(100, 100, 100, 0.35); + border-color: transparent; + box-shadow: none; +} + +.overview-components-dark .search-entry .search-entry-icon { + color: rgba(255, 255, 255, 0.65); +} + +.overview-components-dark .search-section-content, +.overview-components-dark .app-folder .overview-icon { + background-color: rgba(100, 100, 100, 0.35); +} + +/* prevents the extension from interfering with Just Perfection */ +.overview-components-dark.just-perfection .search-section-content { + 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); +} + +/* this shouldn't apply to Dash to Dock */ +.overview-components-dark StBoxLayout>StWidget>#dash>.dash-background { + background-color: rgba(100, 100, 100, 0.35); +} + + +/*** APPFOLDER DIALOG ***/ + +/* +* `.appfolder-dialogs-transparent` +*/ + +.appfolder-dialogs-transparent { + background-color: rgba(0, 0, 0, 0); +} + +.appfolder-dialogs-transparent .folder-name-entry { + color: white; + background-color: rgba(0, 0, 0, 0); + border: 0; + box-shadow: none; +} + +/* +* `.appfolder-dialogs-light` +*/ + +.appfolder-dialogs-light { + background-color: rgba(200, 200, 200, 0.2); +} + +.appfolder-dialogs-light .folder-name-entry { + color: white; + background-color: rgba(200, 200, 200, 0.2); + border: 0; + box-shadow: none; +} + + +/* +* `.appfolder-dialogs-dark` +*/ + +.appfolder-dialogs-dark { + background-color: rgba(100, 100, 100, 0.35); +} + +.appfolder-dialogs-dark .folder-name-entry { + color: white; + background-color: rgba(100, 100, 100, 0.35); + border: 0; + box-shadow: none; +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/applications.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/applications.ui new file mode 100644 index 0000000..0b4b83c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/applications.ui @@ -0,0 +1,163 @@ + + + + + + 25 + 255 + 1 + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/customize-row.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/customize-row.ui new file mode 100644 index 0000000..313bc48 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/customize-row.ui @@ -0,0 +1,143 @@ + + + + + + 0 + 200 + 1 + + + + 0.0 + 1.0 + 0.01 + + + + 0.0 + 1.0 + 0.01 + + + + 0.0 + 2.0 + 0.01 + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/dash.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/dash.ui new file mode 100644 index 0000000..5eac21b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/dash.ui @@ -0,0 +1,73 @@ + + + + + + + Transparent + Light + Dark + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/general.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/general.ui new file mode 100644 index 0000000..73c6b29 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/general.ui @@ -0,0 +1,234 @@ + + + + + + 0 + 200 + 1 + + + + 0.0 + 1.0 + 0.01 + + + + 0.0 + 1.0 + 0.01 + + + + 0.0 + 2.0 + 0.01 + + + + + High performances + Default + High quality + No artifact + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/menu.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/menu.ui new file mode 100644 index 0000000..e7b9210 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/menu.ui @@ -0,0 +1,37 @@ + + + +
+ + Project page + prefs.open-readme + + + Report a Bug + prefs.open-bug-report + + + License + prefs.open-license + + + Donate + + GitHub + prefs.donate-github + + + Ko-fi + prefs.donate-kofi + + +
+
+ + + info_menu_model + heart-filled-symbolic + + + +
\ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/other.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/other.ui new file mode 100644 index 0000000..d1d24f8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/other.ui @@ -0,0 +1,62 @@ + + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/overview.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/overview.ui new file mode 100644 index 0000000..191c70b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/overview.ui @@ -0,0 +1,94 @@ + + + + + + + Do not style + Light + Dark + Transparent + + + + + + Do not style + Transparent + Light + Dark + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/panel.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/panel.ui new file mode 100644 index 0000000..3979f8e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/panel.ui @@ -0,0 +1,126 @@ + + + + + + + Transparent + Light + Dark + + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/window-row.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/window-row.ui new file mode 100644 index 0000000..c4d8201 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/blur-my-shell@aunetx/ui/window-row.ui @@ -0,0 +1,43 @@ + + + + + + Could not pick window, make sure that the extension is enabled. + + \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/LICENSE b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/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. + + + Copyright (C) + + 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) + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/extension.js new file mode 100644 index 0000000..09b0aba --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/extension.js @@ -0,0 +1,1330 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const {Clutter, Graphene, GObject, Shell, St, Meta, Gio} = imports.gi; + +const Util = imports.misc.util; +const Main = imports.ui.main; +const Layout = imports.ui.layout; +const WorkspacesView = imports.ui.workspacesView.WorkspacesView; +const FitMode = imports.ui.workspacesView.FitMode; +const WorkspaceAnimationController = + imports.ui.workspaceAnimation.WorkspaceAnimationController; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const utils = Me.imports.src.utils; +const DragGesture = Me.imports.src.DragGesture.DragGesture; +const Skybox = Me.imports.src.Skybox.Skybox; + +////////////////////////////////////////////////////////////////////////////////////////// +// This extensions tweaks the positioning of workspaces in overview mode and while // +// switching workspaces in desktop mode to make them look like cube faces. // +////////////////////////////////////////////////////////////////////////////////////////// + +// Maximum degrees the cube can be rotated up and down. +const MAX_VERTICAL_ROTATION = 50; + +// Spacing to the screen sides of the vertically rotated cube. +const PADDING_V_ROTATION = 0.2; + +class Extension { + // The constructor is called once when the extension is loaded, not enabled. + constructor() { + this._lastWorkspaceWidth = 0; + } + + // ------------------------------------------------------------------------ public stuff + + // This function could be called after the extension is enabled, which could be done + // from GNOME Tweaks, when you log in or when the screen is unlocked. + enable() { + + // Store a reference to the settings object. + this._settings = ExtensionUtils.getSettings(); + + // We will monkey-patch these methods. Let's store the original ones. + this._origUpdateWorkspacesState = WorkspacesView.prototype._updateWorkspacesState; + this._origGetSpacing = WorkspacesView.prototype._getSpacing; + this._origUpdateVisibility = WorkspacesView.prototype._updateVisibility; + this._origAnimateSwitch = WorkspaceAnimationController.prototype.animateSwitch; + this._origPrepSwitch = WorkspaceAnimationController.prototype._prepareWorkspaceSwitch; + this._origFinalSwitch = WorkspaceAnimationController.prototype._finishWorkspaceSwitch; + + // We may also override these animation times. + this._origWorkspaceSwitchTime = imports.ui.workspacesView.WORKSPACE_SWITCH_TIME; + this._origToOverviewTime = imports.ui.overview.ANIMATION_TIME; + this._origToAppDrawerTime = imports.ui.overviewControls.SIDE_CONTROLS_ANIMATION_TIME; + + // We will use extensionThis to refer to the extension inside the patched methods of + // the WorkspacesView. + const extensionThis = this; + + // Connect the animation times to our settings. + const loadAnimationTimes = () => { + { + const t = this._settings.get_int('overview-transition-time'); + imports.ui.overview.ANIMATION_TIME = (t > 0 ? t : this._origToOverviewTime); + } + { + const t = this._settings.get_int('appgrid-transition-time'); + imports.ui.overviewControls.SIDE_CONTROLS_ANIMATION_TIME = + (t > 0 ? t : this._origToAppDrawerTime); + } + { + const t = this._settings.get_int('workspace-transition-time'); + imports.ui.workspacesView.WORKSPACE_SWITCH_TIME = + (t > 0 ? t : this._origWorkspaceSwitchTime); + } + }; + + this._settings.connect('changed::overview-transition-time', loadAnimationTimes); + this._settings.connect('changed::appgrid-transition-time', loadAnimationTimes); + this._settings.connect('changed::workspace-transition-time', loadAnimationTimes); + + loadAnimationTimes(); + + + // ----------------------------------------------------------------------------------- + // ------------------------------- cubify the overview ------------------------------- + // ----------------------------------------------------------------------------------- + + // Normally, all workspaces outside the current field-of-view are hidden. We want to + // show all workspaces, so we patch this method. The original code is about here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L420 + WorkspacesView.prototype._updateVisibility = function() { + this._workspaces.forEach((w) => { + w.show(); + }); + }; + + // Usually, workspaces are placed next to each other separated by a few pixels (this + // separation is usually computed by the method below). To create the desktop cube, we + // have to position all workspaces on top of each other and rotate the around a pivot + // point in the center of the cube. + // The original arrangement of the workspaces is implemented in WorkspacesView's + // vfunc_allocate() which cannot be monkey-patched. As a workaround, we return a + // negative spacing in the method below... + // The original code is about here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L219 + WorkspacesView.prototype._getSpacing = function(box, fitMode, vertical) { + // We use the "normal" workspace spacing in desktop and app-grid mode. + const origValue = + extensionThis._origGetSpacing.apply(this, [box, fitMode, vertical]); + + if (fitMode == FitMode.ALL) { + return origValue; + } + + // Compute the negative spacing required to arrange workspaces on top of each other. + const overlapValue = -this._workspaces[0].get_preferred_width(box.get_size()[1])[1]; + + // Blend between the negative overlap-spacing and the "normal" spacing value. + const cubeMode = extensionThis._getCubeMode(this); + return Util.lerp(origValue, overlapValue, cubeMode); + }; + + // This is the main method which is called whenever the workspaces need to be + // repositioned. + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L255 + WorkspacesView.prototype._updateWorkspacesState = function() { + // Use the original method if we have just one workspace. + const faceCount = this._workspaces.length; + if (faceCount <= 1) { + extensionThis._origUpdateWorkspacesState.apply(this); + return; + } + + // Here's a minor hack to improve the performance: During the transitions to / from + // the app drawer, this._updateWorkspacesState is called twice a frame. Once from + // the notify handler of this._fitModeAdjustment and thereafter once from the notify + // handler of this._overviewAdjustment. As this seems not so useful (and degrades + // performance a lot), we skip the first call. I am not aware of any cases where + // this._fitModeAdjustment is changed without any of the over adjustments to change + // as well... + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L109 + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L45 + if ((new Error()).stack.includes('fitModeNotify')) { + return; + } + + // Compute blending state from and to the overview, from and to the app grid, and + // from and to the desktop mode. We will use cubeMode to fold and unfold the + // cube, overviewMode to add some depth between windows and backgrounds, and + // appDrawerMode to attenuate the scaling effect of the active workspace. + const appDrawerMode = extensionThis._getAppDrawerMode(this); + const overviewMode = extensionThis._getOverviewMode(this); + const cubeMode = extensionThis._getCubeMode(this); + + // First we need the width of a single workspace. Simply calling + // this._workspaces[0]._background.width does not work in all cases, as this method + // seems to be called also when the background actor is not on the stage. As a hacky + // workaround, we store the last valid workspace width we got and use that value if + // we cannot get a new one... + let workspaceWidth = extensionThis._lastWorkspaceWidth; + const bg = this._workspaces[0]._background; + if (bg.get_stage() && bg.allocation.get_width() > 0) { + workspaceWidth = bg.allocation.get_width(); + + // Add gaps between workspaces in overview mode. + workspaceWidth += + overviewMode * 2 * extensionThis._settings.get_int('workpace-separation'); + + extensionThis._lastWorkspaceWidth = workspaceWidth; + } + + // That's the angle between consecutive workspaces. + const faceAngle = extensionThis._getFaceAngle(faceCount); + + // That's the z-distance from the cube faces to the rotation pivot. + const centerDepth = extensionThis._getCenterDist(workspaceWidth, faceAngle); + + // Apply vertical rotation if required. This comes from the pitch value of the + // modified SwipeTracker created by _addOverviewDragGesture() further below. + this.pivot_point_z = -centerDepth; + this.set_pivot_point(0.5, 0.5); + this.rotation_angle_x = extensionThis._pitch.value * MAX_VERTICAL_ROTATION; + + // During rotations, the cube is scaled down and the windows are "exploded". If we + // are directly facing a cube side, the strengths of both effects are approaching + // zero. The strengths of both effects are small during horizontal rotations to make + // workspace-switching not so obtrusive. However, during vertical rotations, the + // effects are stronger. + const [depthOffset, explode] = extensionThis._getExplodeFactors( + this._scrollAdjustment.value, extensionThis._pitch.value, centerDepth, + this._monitorIndex); + + // Now loop through all workspace and compute the individual rotations. + this._workspaces.forEach((w, index) => { + // First update the corner radii. Corners are only rounded in overview. + w.stateAdjustment.value = overviewMode; + + // Now update the rotation of the cube face. The rotation center is -centerDepth + // units behind the front face. + w.pivot_point_z = -centerDepth; + + // Make cube smaller during rotations. + w.translation_z = -depthOffset; + + // The rotation angle is transitioned proportional to cubeMode^1.5. This slows + // down the rotation a bit closer to the desktop and to the app drawer. + w.rotation_angle_y = + Math.pow(cubeMode, 1.5) * (-this._scrollAdjustment.value + index) * faceAngle; + + // Distance to being the active workspace in [-1...0...1]. + const dist = Math.clamp(index - this._scrollAdjustment.value, -1, 1); + + // This moves next and previous workspaces a bit to the left and right. This + // ensures that we can actually see them if we look at the cube from the front. + // The value is set to zero if we have five or more workspaces. + if (faceCount <= 4) { + w.translation_x = + dist * overviewMode * extensionThis._settings.get_int('horizontal-stretch'); + } else { + w.translation_x = 0; + } + + // Update opacity only in overview mode. + const opacityA = extensionThis._settings.get_int('active-workpace-opacity'); + const opacityB = extensionThis._settings.get_int('inactive-workpace-opacity'); + const opacity = Util.lerp(opacityA, opacityB, Math.abs(dist)); + w._background.set_opacity(Util.lerp(255, opacity, overviewMode)); + + // Update workspace scale only in app grid mode. The 0.94 is supposed to be the + // same value as the WORKSPACE_INACTIVE_SCALE defined here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L21 + // As this is defined as 'const', we cannot access it here. But the exact value + // also not really matters... + const scale = Util.lerp(1, 0.94, Math.abs(dist) * appDrawerMode); + w.set_scale(scale, scale); + + // Now we add some depth separation between the window clones. If the explode + // factor becomes too small, the depth sorting becomes non-deterministic. + if (explode > 0.001) { + + const sortedActors = w._container.layout_manager._sortedWindows; + + // Distribute the window clones translation_z values between zero and + // explode. + sortedActors.forEach((windowActor, j) => { + windowActor.translation_z = explode * (j + 1) / sortedActors.length; + }); + + // Now sort the window clones according to the orthogonal distance of the actor + // planes to the camera. This ensures proper depth sorting among the window + // clones. + if (sortedActors.length > 1) { + extensionThis._depthSortWindowActors(w._container.get_children(), + this._monitorIndex); + } + } + + // Now we sort the children of the workspace (e.g. the background actor + // and the container for the window clones) by their orthogonal distance to the + // virtual camera. We add a tiny translation to the window-clone container to + // allow for proper sorting. + w._container.translation_z = 1; + extensionThis._depthSortWindowActors(w.get_children(), this._monitorIndex); + }); + + // The depth-sorting of cube faces is quite simple, we sort them by increasing + // rotation angle so that they are drawn back-to-front. + extensionThis._depthSortCubeFaces(this._workspaces); + }; + + + // ----------------------------------------------------------------------------------- + // --------------------- cubify workspace-switch in desktop mode --------------------- + // ----------------------------------------------------------------------------------- + + // Here, we extend the WorkspaceAnimationController's animateSwitch method in order to + // be able to modify the animation duration for switching workspaces in desktop mode. + // We have to do it like this since the time is hard-coded with a constant: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L11 + WorkspaceAnimationController.prototype.animateSwitch = function(...params) { + // Call the original method. This sets up the progress transitions which we tweak + // thereafter. + extensionThis._origAnimateSwitch.apply(this, params); + + // Now update the transition durations. + const duration = extensionThis._settings.get_int('workspace-transition-time'); + if (duration > 0) { + for (const monitorGroup of this._switchData.monitors) { + monitorGroup.get_transition('progress').set_duration(duration); + } + } + }; + + // This override rotates the workspaces during the transition to look like cube + // faces. The original movement of the workspaces is implemented in the setter of + // the progress property. We do not touch this, as keeping track of this progress + // is rather important. Instead, we listen to progress changes and tweak the + // transformation accordingly. + // This lambda is called in two places (further down), once for updates of the + // progress property, once for updates during gesture swipes. The latter does not + // trigger notify signals of the former for some reason... + const updateMonitorGroup = (group) => { + // First, we prevent any horizontal movement by countering the translation. We + // cannot simply set the x property to zero as this is used to track the + // progress. + group._container.translation_x = -group._container.x; + + // That's the desired angle between consecutive workspaces. + const faceAngle = extensionThis._getFaceAngle(group._workspaceGroups.length); + + // That's the z-distance from the cube faces to the rotation pivot. + const centerDepth = + extensionThis._getCenterDist(group._workspaceGroups[0].width, faceAngle); + + // Apply vertical rotation if required. This comes from the pitch value of the + // modified SwipeTracker created by _addDesktopDragGesture() further below. + group._container.pivot_point_z = -centerDepth; + group._container.set_pivot_point(0.5, 0.5); + group._container.rotation_angle_x = + extensionThis._pitch.value * MAX_VERTICAL_ROTATION; + + // During rotations, the cube is scaled down and the windows are "exploded". If we + // are directly facing a cube side, the strengths of both effects are approaching + // zero. The strengths of both effects are small during horizontal rotations to make + // workspace-switching not so obtrusive. However, during vertical rotations, the + // effects are stronger. + const [depthOffset, explode] = extensionThis._getExplodeFactors( + group.progress, extensionThis._pitch.value, centerDepth, group._monitor.index); + + // Rotate the individual faces. + group._workspaceGroups.forEach((child, i) => { + child.set_pivot_point_z(-centerDepth); + child.set_pivot_point(0.5, 0.5); + child.rotation_angle_y = (i - group.progress) * faceAngle; + child.translation_z = -depthOffset; + child.clip_to_allocation = false; + + // Counter the horizontal movement. + child.translation_x = -child.x; + + // Make cube transparent during vertical rotations. + child._background.opacity = 255 * (1.0 - Math.abs(extensionThis._pitch.value)); + + // Now we add some depth separation between the window clones. We get the stacking + // order from the global window list. If the explode factor becomes too small, the + // depth sorting becomes non-deterministic. + if (explode > 0.001) { + const windowActors = global.get_window_actors().filter(w => { + return child._shouldShowWindow(w.meta_window); + }); + + // Distribute the window clones translation_z values between zero and + // explode. + windowActors.forEach((windowActor, j) => { + const record = child._windowRecords.find(r => r.windowActor === windowActor); + if (record) { + record.clone.translation_z = explode * (j + 1) / windowActors.length; + } + }); + + // Now sort the window clones and the background actor according to the + // orthogonal distance of the actor planes to the camera. This ensures proper + // depth sorting. + extensionThis._depthSortWindowActors(child.get_children(), + group._monitor.index); + } + }); + + // The depth-sorting of cube faces is quite simple, we sort them by increasing + // rotation angle. + extensionThis._depthSortCubeFaces(group._workspaceGroups); + + // Update horizontal rotation of the background panorama during workspace switches. + if (this._skybox) { + this._skybox.yaw = + 2 * Math.PI * group.progress / global.workspaceManager.get_n_workspaces(); + } + }; + + // Whenever a workspace-switch is about to happen, we tweak the MonitorGroup class a + // bit to arrange the workspaces in a cube-like fashion. We have to adjust to parts of + // the code as the automatic transitions (e.g. when switching with key combinations) + // are handled differently than the gesture based switches. + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L299 + WorkspaceAnimationController.prototype._prepareWorkspaceSwitch = function() { + // Here, we call the original method without any arguments. Usually, GNOME Shell + // "skips" workspaces when switching to a workspace which is more than one workspace + // to the left or the right. This behavior is not desirable for thr cube, as it + // messes with your spatial memory. If no workspaceIndices are given to this method, + // all workspaces will be shown during the workspace switch. + extensionThis._origPrepSwitch.apply(this, []); + + // Now tweak the monitor groups. + this._switchData.monitors.forEach(m => { + // Call the method above whenever the transition progress changes. + m.connect('notify::progress', () => updateMonitorGroup(m)); + + // Call the method above whenever a gesture is active. + const orig = m.updateSwipeForMonitor; + m.updateSwipeForMonitor = function(progress, baseMonitorGroup) { + orig.apply(m, [progress, baseMonitorGroup]); + updateMonitorGroup(m); + }; + }); + + // Make sure that the background panorama is drawn above the window group during a + // workspace switch. + if (extensionThis._skybox) { + extensionThis._skybox.get_parent().remove_child(extensionThis._skybox); + Main.uiGroup.insert_child_above(extensionThis._skybox, global.window_group); + + // If the workspaces are only on the primary monitor, the skybox would cover all + // other non-rotating screens. Therefore, we temporarily limit its size to the + // primary monitor's size. + if (Meta.prefs_get_workspaces_only_on_primary()) { + const monitor = + global.display.get_monitor_geometry(global.display.get_primary_monitor()); + extensionThis._skybox.width = monitor.width; + extensionThis._skybox.height = monitor.height; + extensionThis._skybox.x = monitor.x; + extensionThis._skybox.y = monitor.y; + } + } + }; + + // Re-attach the background panorama to the stage once the workspace switch is done. + WorkspaceAnimationController.prototype._finishWorkspaceSwitch = function(...params) { + extensionThis._origFinalSwitch.apply(this, params); + + // Make sure that the skybox covers the entire stage again. + if (extensionThis._skybox) { + extensionThis._skybox.get_parent().remove_child(extensionThis._skybox); + global.stage.insert_child_below(extensionThis._skybox, null); + + if (Meta.prefs_get_workspaces_only_on_primary()) { + extensionThis._skybox.width = global.stage.width; + extensionThis._skybox.height = global.stage.height; + extensionThis._skybox.x = global.stage.x; + extensionThis._skybox.y = global.stage.y; + } + } + }; + + + // ----------------------------------------------------------------------------------- + // ------------------------- enable cube rotation by dragging ------------------------ + // ----------------------------------------------------------------------------------- + + // Usually, in GNOME Shell 40+, workspaces are move horizontally. We tweaked this to + // look like a horizontal rotation above. To store the current vertical rotation, we + // use the adjustment below. + this._pitch = new St.Adjustment({actor: global.stage, lower: -1, upper: 1}); + + // The overview's SwipeTracker will control the _overviewAdjustment of the + // WorkspacesDisplay. However, only horizontal swipes will update this adjustment. If + // only our pitch adjustment is changed (e.g. the user moved the mouse only + // vertically), the _overviewAdjustment will not change and therefore the workspaces + // will not been redrawn. Here we force redrawing by notifying changes if the pitch + // value changes. + this._pitch.connect('notify::value', () => { + if (Main.actionMode == Shell.ActionMode.OVERVIEW) { + Main.overview._overview._controls._workspacesDisplay._overviewAdjustment.notify( + 'value'); + } + }); + + // In GNOME Shell, SwipeTrackers are used all over the place to capture swipe + // gestures. There's one for entering the overview, one for switching workspaces in + // desktop mode, one for switching workspaces in overview mode, one for horizontal + // scrolling in the app drawer, and many more. The ones used for workspace-switching + // usually do not respond to single-click dragging but only to multi-touch gestures. + // We want to be able to rotate the cube with the left mouse button, so we add an + // additional gesture to these two SwipeTracker instances tracking single-click drags. + + // Add single-click drag gesture to the desktop. + if (this._settings.get_boolean('enable-desktop-dragging')) { + this._addDesktopDragGesture(); + } + + this._settings.connect('changed::enable-desktop-dragging', () => { + if (this._settings.get_boolean('enable-desktop-dragging')) { + this._addDesktopDragGesture(); + } else { + this._removeDesktopDragGesture(); + } + }); + + // Add single-click drag gesture to the panel. + if (this._settings.get_boolean('enable-panel-dragging')) { + this._addPanelDragGesture(); + } + + this._settings.connect('changed::enable-panel-dragging', () => { + if (this._settings.get_boolean('enable-panel-dragging')) { + this._addPanelDragGesture(); + } else { + this._removePanelDragGesture(); + } + }); + + // Add single-click drag gesture to the overview. + if (this._settings.get_boolean('enable-overview-dragging')) { + this._addOverviewDragGesture(); + } + + this._settings.connect('changed::enable-overview-dragging', () => { + if (this._settings.get_boolean('enable-overview-dragging')) { + this._addOverviewDragGesture(); + } else { + this._removeOverviewDragGesture(); + } + }); + + + // ----------------------------------------------------------------------------------- + // ---------------------------------- add the skybox --------------------------------- + // ----------------------------------------------------------------------------------- + + // This is called whenever the skybox texture setting is changed. + const updateSkybox = () => { + // First, delete the existing skybox. + if (this._skybox) { + this._skybox.destroy(); + delete this._skybox; + } + + const file = this._settings.get_string('background-panorama'); + + // Then, load a new one (if any). + if (file != '') { + try { + this._skybox = new Skybox(file); + + // We add the skybox below everything. + global.stage.insert_child_below(this._skybox, null); + + // Make sure that the skybox covers the entire stage. + global.stage.bind_property('width', this._skybox, 'width', + GObject.BindingFlags.SYNC_CREATE); + global.stage.bind_property('height', this._skybox, 'height', + GObject.BindingFlags.SYNC_CREATE); + + } catch (error) { + utils.debug('Failed to set skybox: ' + error); + } + } + }; + + // Update the skybox whenever the corresponding setting is changed. + this._settings.connect('changed::background-panorama', updateSkybox); + updateSkybox(); + + // Update vertical rotation of the background panorama. + this._pitch.connect('notify::value', () => { + if (this._skybox) { + this._skybox.pitch = (this._pitch.value * MAX_VERTICAL_ROTATION) * Math.PI / 180; + } + }); + + // Update horizontal rotation of the background panorama during workspace switches in + // the overview. + Main.overview._overview.controls._workspaceAdjustment.connect('notify::value', () => { + if (this._skybox) { + this._skybox.yaw = 2 * Math.PI * + Main.overview._overview.controls._workspaceAdjustment.value / + global.workspaceManager.get_n_workspaces(); + } + }); + + + // ----------------------------------------------------------------------------------- + // ----------------------- enable edge-drag workspace-switches ----------------------- + // ----------------------------------------------------------------------------------- + + // We add two Meta.Barriers, one at each side of the stage. If the pointer hits one of + // these with enough pressure while dragging a window, we initiate a workspace-switch. + // The last parameter (0) is actually supposed to be a bitwise combination of + // Shell.ActionModes. The pressure barrier will only trigger, if Main.actionMode + // equals one of the given action modes. This works well for Shell.ActionMode.NORMAL + // and Shell.ActionMode.OVERVIEW, however it does not work for Shell.ActionMode.NONE + // (which actually equals zero). However, when we want the barriers to also trigger in + // Shell.ActionMode.NONE, as this is the mode during a drag-operation in the overview. + // Therefore, we modify the _onBarrierHit method of the pressure barrier to completely + // ignore this parameter. Instead, we check for the correct action mode in the trigger + // handler. + this._pressureBarrier = + new Layout.PressureBarrier(this._settings.get_int('edge-switch-pressure'), + Layout.HOT_CORNER_PRESSURE_TIMEOUT, 0); + + // Update pressure threshold when the corresponding settings key changes. + this._settings.connect('changed::edge-switch-pressure', () => { + this._pressureBarrier._threshold = this._settings.get_int('edge-switch-pressure'); + }); + + // This is an exact copy of the original _onBarrierHit, with only one line disabled to + // ignore the given ActionMode. + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/layout.js#L1366 + this._pressureBarrier._onBarrierHit = function(barrier, event) { + barrier._isHit = true; + + // If we've triggered the barrier, wait until the pointer has the + // left the barrier hitbox until we trigger it again. + if (this._isTriggered) return; + + if (this._eventFilter && this._eventFilter(event)) return; + + // Throw out all events not in the proper keybinding mode + // if (!(this._actionMode & Main.actionMode)) return; + + let slide = this._getDistanceAlongBarrier(barrier, event); + let distance = this._getDistanceAcrossBarrier(barrier, event); + + if (distance >= this._threshold) { + this._trigger(); + return; + } + + // Throw out events where the cursor is move more + // along the axis of the barrier than moving with + // the barrier. + if (slide > distance) return; + + this._lastTime = event.time; + + this._trimBarrierEvents(); + distance = Math.min(15, distance); + + this._barrierEvents.push([event.time, distance]); + this._currentPressure += distance; + + if (this._currentPressure >= this._threshold) this._trigger(); + }; + + // Now we add the left and right barrier to the pressure barrier. + const createBarriers = () => { + if (this._leftBarrier) { + this._pressureBarrier.removeBarrier(this._leftBarrier); + this._leftBarrier.destroy(); + } + + if (this._rightBarrier) { + this._pressureBarrier.removeBarrier(this._rightBarrier); + this._rightBarrier.destroy(); + } + + this._leftBarrier = new Meta.Barrier({ + display: global.display, + x1: 0, + x2: 0, + y1: 1, + y2: global.stage.height, + directions: Meta.BarrierDirection.POSITIVE_X, + }); + + this._rightBarrier = new Meta.Barrier({ + display: global.display, + x1: global.stage.width, + x2: global.stage.width, + y1: 1, + y2: global.stage.height, + directions: Meta.BarrierDirection.NEGATIVE_X, + }); + + this._pressureBarrier.addBarrier(this._leftBarrier); + this._pressureBarrier.addBarrier(this._rightBarrier); + }; + + // Re-create the barriers whenever the stage's allocation is changed. + this._stageAllocationID = global.stage.connect('notify::allocation', createBarriers); + createBarriers(); + + // When the pressure barrier is triggered, the corresponding setting is enabled, and a + // window is currently dragged, we move the dragged window to the adjacent workspace + // and activate it as well. + this._pressureBarrier.connect('trigger', () => { + const direction = + this._leftBarrier._isHit ? Meta.MotionDirection.LEFT : Meta.MotionDirection.RIGHT; + + const newWorkspace = + global.workspace_manager.get_active_workspace().get_neighbor(direction); + + if (Main.actionMode == Shell.ActionMode.NORMAL && this._draggedWindow && + this._settings.get_boolean('enable-desktop-edge-switch')) { + Main.wm.actionMoveWindow(this._draggedWindow, newWorkspace); + } else if (Main.actionMode == Shell.ActionMode.NONE && Main.overview.visible && + this._settings.get_boolean('enable-overview-edge-switch')) { + newWorkspace.activate(global.get_current_time()); + } + }); + + // Keep a reference to the currently dragged window. + global.display.connect('grab-op-begin', (d, win, op) => { + if (op == Meta.GrabOp.MOVING) { + this._draggedWindow = win; + } + }); + + // Release the reference to the currently dragged window. + global.display.connect('grab-op-end', (d, win, op) => { + if (op == Meta.GrabOp.MOVING) { + this._draggedWindow = null; + } + }); + + + // ----------------------------------------------------------------------------------- + // ------------------- fix perspective of multi-monitor setups ----------------------- + // ----------------------------------------------------------------------------------- + + // Usually, GNOME Shell uses one central perspective for all monitors combined. This + // results in a somewhat sheared appearance of the cube on multi-monitor setups where + // the primary monitor is not in the middle (or cubes are shown on multiple monitors). + // With the code below, we modify the projection and view matrices for each monitor so + // that each monitor uses its own central perspective. This seems to be possible on + // Wayland only. On X11, there's only one set of projection and view matrices for all + // monitors combined, so we tweak them so that the projection center is in the middle + // of the primary monitor. So it will at least only look bad on X11 if the cube is + // shown on all monitors... + const updateMonitorPerspective = () => { + // Disable the perspective fixes first... + this._disablePerspectiveCorrection(); + + // Store this so we do not have to get it too often. + this._enablePerMonitorPerspective = + this._settings.get_boolean('per-monitor-perspective') && + global.display.get_n_monitors() > 1; + + // ... and then enable them if required. + if (this._enablePerMonitorPerspective) { + this._enablePerspectiveCorrection(); + } + }; + + this._settings.connect('changed::per-monitor-perspective', updateMonitorPerspective); + this._monitorsChangedID = + Meta.MonitorManager.get().connect('monitors-changed', updateMonitorPerspective); + + updateMonitorPerspective(); + } + + // This function could be called after the extension is uninstalled, disabled in GNOME + // Tweaks, when you log out or when the screen locks. + disable() { + + // Restore the original behavior. + WorkspacesView.prototype._updateWorkspacesState = this._origUpdateWorkspacesState; + WorkspacesView.prototype._getSpacing = this._origGetSpacing; + WorkspacesView.prototype._updateVisibility = this._origUpdateVisibility; + WorkspaceAnimationController.prototype.animateSwitch = this._origAnimateSwitch; + WorkspaceAnimationController.prototype._prepareWorkspaceSwitch = this._origPrepSwitch; + WorkspaceAnimationController.prototype._finishWorkspaceSwitch = this._origFinalSwitch; + + imports.ui.workspacesView.WORKSPACE_SWITCH_TIME = this._origWorkspaceSwitchTime; + imports.ui.overview.ANIMATION_TIME = this._origToOverviewTime; + imports.ui.overviewControls.SIDE_CONTROLS_ANIMATION_TIME = this._origToAppDrawerTime; + + // Remove all drag-to-rotate gestures. + this._removeDesktopDragGesture(); + this._removePanelDragGesture(); + this._removeOverviewDragGesture(); + + // Clean up skybox. + if (this._skybox) { + this._skybox.destroy(); + this._skybox = null; + } + + // Clean up the edge-workspace-switching. + global.stage.disconnect(this._stageAllocationID); + + this._pressureBarrier.destroy(); + this._leftBarrier.destroy(); + this._rightBarrier.destroy(); + + this._pressureBarrier = null; + this._leftBarrier = null; + this._rightBarrier = null; + + // Clean up perspective correction. + this._disablePerspectiveCorrection(); + Meta.MonitorManager.get().disconnect(this._monitorsChangedID); + + // Make sure that the settings object is freed. + this._settings = null; + } + + // ----------------------------------------------------------------------- private stuff + + // Calls inhibit_culling on the given actor and recursively on all mapped children. + _inhibitCulling(actor) { + if (actor.mapped) { + actor.inhibit_culling(); + actor._culling_inhibited_by_desktop_cube = true; + actor.get_children().forEach(c => this._inhibitCulling(c)); + } + }; + + // Calls uninhibit_culling on the given actor and recursively on all children. It will + // only call uninhibit_culling() on those actors which were inhibited before. + _uninhibitCulling(actor) { + if (actor._culling_inhibited_by_desktop_cube) { + delete actor._culling_inhibited_by_desktop_cube; + actor.uninhibit_culling(); + actor.get_children().forEach(c => this._uninhibitCulling(c)); + } + }; + + // Returns a value between [0...1] blending between overview (0) and app grid mode (1). + _getAppDrawerMode(workspacesView) { + return workspacesView._fitModeAdjustment.value; + } + + // Returns a value between [0...1] blending between desktop / app drawer mode (0) and + // overview mode (1). + _getOverviewMode(workspacesView) { + return workspacesView._overviewAdjustment.value - + 2 * this._getAppDrawerMode(workspacesView); + } + + // Returns a value between [0...1]. If it's 0, the cube should be unfolded, if it's 1, + // the cube should be drawn like, well, a cube :). + _getCubeMode(workspacesView) { + return 1 - this._getAppDrawerMode(workspacesView) + } + + // Returns the angle between consecutive workspaces. + _getFaceAngle(faceCount) { + + // With this setting, our "cube" only covers 180°, if there are only two workspaces, + // it covers 90°. This prevents the affordance that it could be possible to switch + // from the last ot the first workspace. + if (this._settings.get_boolean('last-first-gap')) { + return (faceCount == 2 ? 90 : 180) / (faceCount - 1); + } + + // Else the "cube" covers 360°. + return 360.0 / faceCount; + } + + // Returns the z-distance from the cube faces to the rotation pivot. + _getCenterDist(workspaceWidth, faceAngle) { + let centerDepth = workspaceWidth / 2; + if (faceAngle < 180) { + centerDepth /= Math.tan(faceAngle * 0.5 * Math.PI / 180); + } + return centerDepth; + } + + // This sorts the given list of children actors (which are supposed to be attached to + // the same parent) by increasing absolute rotation-y angle. This is used for + // depth-sorting, as cube faces which are less rotated, are in front of others. + _depthSortCubeFaces(actors) { + // First create a copy of the actors list and sort it by decreasing rotation angle. + const copy = actors.slice(); + copy.sort((a, b) => { + return Math.abs(b.rotation_angle_y) - Math.abs(a.rotation_angle_y); + }); + + // Then sort the children actors accordingly. + const parent = actors[0].get_parent(); + for (let i = 0; i < copy.length; i++) { + parent.set_child_at_index(copy[i], -1); + } + } + + // This sorts the given list of children actors (which are supposed to be attached to + // the same parent) by increasing orthogonal distance to the camera. To do this, the + // camera position is projected onto the plane defined by the actor and the absolute + // distance from the camera to its projected position is computed. This is used for + // depth-sorting a list of parallel actors. + _depthSortWindowActors(actors, monitorIndex) { + + // Sanity check. + if (actors.length <= 1) { + return; + } + + // First, compute distance of virtual camera to the front workspace plane. + const camera = new Graphene.Point3D({ + x: global.stage.width / 2, + y: global.stage.height / 2, + z: global.stage.height / + (2 * Math.tan(global.stage.perspective.fovy / 2 * Math.PI / 180)) + }); + + // All actors are expected to share the same parent. + const parent = actors[0].get_parent(); + + // If the perspective is corrected for multi-monitor setups, the virtual camera is not + // in the middle of the stage but rather in front of each monitor. + if (this._enablePerMonitorPerspective) { + + let monitor; + + if (Meta.is_wayland_compositor()) { + + // On Wayland, each monitor should have its own StageView. Therefore, the virtual + // camera has been positioned in front of each monitor separately. + monitor = global.display.get_monitor_geometry(monitorIndex); + + } else { + + // On X11, there's only one StageView. We move the virtual camera so that it is in + // front of the primary monitor. + monitor = + global.display.get_monitor_geometry(global.display.get_primary_monitor()); + } + + camera.x = monitor.x + monitor.width / 2; + camera.y = monitor.y + monitor.height / 2; + } + + // Create a list of the orthogonal distances to the camera for each actor. + const distances = actors.map((a, i) => { + // A point on the actor plane. + const onActor = a.apply_relative_transform_to_point( + null, new Graphene.Point3D({x: 0, y: 0, z: 0})); + + // A point one unit above the actor plane. + const aboveActor = a.apply_relative_transform_to_point( + null, new Graphene.Point3D({x: 0, y: 0, z: 1000})); + + // The normal vector on the actor plane. + const normal = new Graphene.Point3D({ + x: aboveActor.x - onActor.x, + y: aboveActor.y - onActor.y, + z: aboveActor.z - onActor.z, + }); + + const length = + Math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z); + normal.x /= length; + normal.y /= length; + normal.z /= length; + + onActor.x -= camera.x; + onActor.y -= camera.y; + onActor.z -= camera.z; + + // Return the length of the projected vector. + return { + index: i, + distance: onActor.x * normal.x + onActor.y * normal.y + onActor.z * normal.z + }; + }); + + // Sort by decreasing distance. + distances.sort((a, b) => { + return Math.abs(b.distance) - Math.abs(a.distance); + }); + + // Then use this to create a sorted list of actors. + const copy = distances.map(e => { + return actors[e.index]; + }); + + // Finally, sort the children actors accordingly. + for (let i = 0; i < copy.length; i++) { + parent.set_child_at_index(copy[i], -1); + } + } + + // During rotations, the cube is scaled down and the windows are "exploded". If we + // are directly facing a cube side, the strengths of both effects are approaching + // zero. The strengths of both effects are small during horizontal rotations to make + // workspace-switching not so obtrusive. However, during vertical rotations, the + // effects are stronger. + // This method returns two values: + // result[0]: A translation value by which the cube should be moved backwards. + // result[1]: A translation value by which windows may be moved away from the cube. + _getExplodeFactors(hRotation, vRotation, centerDepth, monitorIndex) { + + // These are zero if we are facing a workspace and one if we look directly at an + // edge between adjacent workspaces or if the cube is rotated vertically + // respectively. + const hFactor = 1.0 - 2.0 * Math.abs(hRotation % 1 - 0.5); + const vFactor = Math.abs(vRotation); + + // For horizontal rotations, we want to scale the cube (or rather move it backwards) + // a tiny bit to reveal a bit of parallax. However, if we have many cube sides, this + // looks weird, so we reduce the effect there. We use the offset which would make + // the cube's corners stay behind the original workspace faces during he rotation. + const monitor = global.display.get_monitor_geometry(monitorIndex); + const cornerDist = + Math.sqrt(Math.pow(centerDepth, 2) + Math.pow(monitor.width / 2, 2)); + const hDepthOffset = + this._settings.get_double('window-parallax') * (cornerDist - centerDepth); + + // The explode factor is set to the hDepthOffset value to make the front-most + // window stay at a constant depth. + const hExplode = hDepthOffset; + + // For vertical rotations, we move the cube backwards to reveal everything. The + // maximum explode width is set to half of the workspace size. + const vExplode = this._settings.get_boolean('do-explode') ? + Math.max(monitor.width, monitor.height) / 2 : + 0; + const diameter = 2 * (vExplode + centerDepth); + const camDist = + monitor.height / (2 * Math.tan(global.stage.perspective.fovy / 2 * Math.PI / 180)); + const vDepthOffset = + (1 + PADDING_V_ROTATION) * diameter * camDist / monitor.width - centerDepth; + + // Use current maximum of both values. + const depthOffset = Math.max(hFactor * hDepthOffset, vFactor * vDepthOffset); + const explode = Math.max(hFactor * hExplode, vFactor * vExplode); + + // Do not explode the cube in app drawer state. The stateAdjustment is... + // ... 0 on the desktop + // ... 1 in the window picker + // ... 2 in the app drawer + const windowPickerFactor = + Math.min(1.0, 2.0 - Main.overview._overview.controls._stateAdjustment.value); + + return [depthOffset * windowPickerFactor, explode * windowPickerFactor]; + } + + // Usually, GNOME Shell uses one central perspective for all monitors combined. This + // results in a somewhat sheared appearance of the cube on multi-monitor setups where + // the primary monitor is not in the middle (or cubes are shown on multiple monitors). + // With the code below, we modify the projection and view matrices for each monitor so + // that each monitor uses its own central perspective. This seems to be possible on + // Wayland only. On X11, there's only one set of projection and view matrices for all + // monitors combined, so we tweak them so that the projection center is in the middle of + // the primary monitor. So it will at least only look bad on X11 if the cube is shown on + // all monitors... + _enablePerspectiveCorrection() { + + this._stageBeforeUpdateID = global.stage.connect('before-update', (stage, view) => { + // Do nothing if neither overview or desktop switcher are shown. + if (!Main.overview.visible && Main.wm._workspaceAnimation._switchData == null) { + return; + } + + // Usually, the virtual camera is positioned centered in front of the stage. We will + // move the virtual camera around. These variables will be the new stage-relative + // coordinates of the virtual camera. + let cameraX, cameraY; + + if (Meta.is_wayland_compositor()) { + + // On Wayland, each monitor has its own StageView. Therefore we can move the + // virtual camera for each monitor separately. + cameraX = view.layout.x + view.layout.width / 2; + cameraY = view.layout.y + view.layout.height / 2; + + } else { + + // On X11, there's only one StageView. We move the virtual camera so that it is in + // front of the primary monitor. + const primaryMonitorRect = + global.display.get_monitor_geometry(global.display.get_primary_monitor()); + + cameraX = primaryMonitorRect.x + primaryMonitorRect.width / 2; + cameraY = primaryMonitorRect.y + primaryMonitorRect.height / 2; + } + + // This is the offset to the original, centered camera position. Y is flipped due to + // some negative scaling at some point in Mutter. + const camOffsetX = stage.width / 2 - cameraX; + const camOffsetY = cameraY - stage.height / 2; + + const z_near = stage.perspective.z_near; + const z_far = stage.perspective.z_far; + + // The code below is copied from Mutter's Clutter. + // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2255 + const A = 0.57735025882720947265625; + const B = 0.866025388240814208984375; + const C = 0.86162912845611572265625; + const D = 0.00872653536498546600341796875; + + const z_2d = z_near * A * B * C / D + z_near; + + // The code below is copied from Mutter's Clutter as well. + // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2270 + const top = z_near * Math.tan(stage.perspective.fovy * Math.PI / 360.0); + const left = -top * stage.perspective.aspect; + const right = top * stage.perspective.aspect; + const bottom = -top; + + const left_2d_plane = left / z_near * z_2d; + const right_2d_plane = right / z_near * z_2d; + const bottom_2d_plane = bottom / z_near * z_2d; + const top_2d_plane = top / z_near * z_2d; + + const width_2d_start = right_2d_plane - left_2d_plane; + const height_2d_start = top_2d_plane - bottom_2d_plane; + + const width_scale = width_2d_start / stage.width; + const height_scale = height_2d_start / stage.height; + // End of the copy-paste code. + + // Compute the required offset of the frustum planes at the near plane. This + // basically updates the projection matrix according to our new camera position. + const offsetX = camOffsetX * width_scale / z_2d * z_near; + const offsetY = camOffsetY * height_scale / z_2d * z_near; + + // Set the new frustum. + view.get_framebuffer().frustum(left + offsetX, right + offsetX, bottom + offsetY, + top + offsetY, z_near, z_far); + + // Translate the virtual camera. This basically updates the view matrix according to + // our new camera position. + view.get_framebuffer().push_matrix(); + view.get_framebuffer().translate(camOffsetX * width_scale, + camOffsetY * height_scale, 0); + + // If the perspective of each monitor is computed separately, the culling of GNOME + // Shell does not work anymore as it still uses the original frustum. The only + // workaround is to disable culling altogether. This will be bad performance-wise, + // but I do not see an alternative. + // If the overview is shown, we inhibit culling for the WorkspacesDisplay. If the + // desktop-workspace-switcher is shown, we inhibit culling for all shown monitor + // groups. + if (Main.overview.visible) { + this._inhibitCulling(Main.overview._overview.controls._workspacesDisplay); + } else if (Main.wm._workspaceAnimation._switchData) { + Main.wm._workspaceAnimation._switchData.monitors.forEach(m => { + this._inhibitCulling(m); + }); + } + }); + + // Revert the matrix changes before the update, + this._stageAfterUpdateID = global.stage.connect('after-update', (stage, view) => { + // Nothing to do if neither overview or desktop switcher are shown. + if (!Main.overview.visible && Main.wm._workspaceAnimation._switchData == null) { + return; + } + + view.get_framebuffer().pop_matrix(); + view.get_framebuffer().perspective(stage.perspective.fovy, stage.perspective.aspect, + stage.perspective.z_near, + stage.perspective.z_far); + + // Re-enable culling for all relevant actors. + if (Main.overview.visible) { + this._uninhibitCulling(Main.overview._overview.controls._workspacesDisplay); + } else if (Main.wm._workspaceAnimation._switchData) { + Main.wm._workspaceAnimation._switchData.monitors.forEach(m => { + this._uninhibitCulling(m); + }); + } + }); + } + + // Reverts the changes done with the method above. + _disablePerspectiveCorrection() { + + if (this._stageBeforeUpdateID) { + global.stage.disconnect(this._stageBeforeUpdateID); + this._stageBeforeUpdateID = 0; + } + + if (this._stageAfterUpdateID) { + global.stage.disconnect(this._stageAfterUpdateID); + this._stageAfterUpdateID = 0; + } + } + + // This creates a custom drag gesture and adds it to the given SwipeTracker. The swipe + // tracker will now also respond to horizontal drags. The additional gesture also + // reports vertical drag movements via the "pitch" property. This method returns an + // object containing the gesture, an St.Adjustment which will contain this pitch value, + // and a connection ID which is used by _removeDragGesture() to clean up. When the + // SwipeTracker's gesture ends, the St.Adjustment's value will be eased to zero. + _addDragGesture(actor, tracker, mode) { + const gesture = new DragGesture(actor, mode); + gesture.connect('begin', tracker._beginGesture.bind(tracker)); + gesture.connect('update', tracker._updateGesture.bind(tracker)); + gesture.connect('end', tracker._endTouchGesture.bind(tracker)); + tracker.bind_property('distance', gesture, 'distance', + GObject.BindingFlags.SYNC_CREATE); + + // Update the gesture's sensitivity when the corresponding settings value changes. + this._settings.bind('mouse-rotation-speed', gesture, 'sensitivity', + Gio.SettingsBindFlags.GET); + + // Connect the gesture's pitch property to the pitch adjustment. + gesture.bind_property('pitch', this._pitch, 'value', 0); + + // Ease the pitch adjustment to zero if the SwipeTracker reports an ended gesture. + // This ensures that the cube smoothly rotates back when released. The end-signal + // returns a suitable duration for this, however this depends on the horizontal + // rotation required to move the cube back. Here, we compute a duration required for + // the vertical rotation and use the maximum of both values for the final easing. + const gestureEndID = tracker.connect('end', (g, duration) => { + this._pitch.remove_transition('value'); + this._pitch.ease(0, { + duration: Math.max(500 * Math.abs(this._pitch.value), duration), + mode: Clutter.AnimationMode.EASE_OUT_CUBIC, + }); + }); + + // We return all things which are required to remove the gesture again. This can be + // done with the _removeDragGesture() method below. + return { + actor: actor, + tracker: tracker, + gesture: gesture, + trackerConnection: gestureEndID + }; + } + + // Removes a single-click drag gesture created earlier via _addDragGesture(). The info + // parameter should be the object returned by _addDragGesture(). + _removeDragGesture(info) { + info.gesture.destroy(); + info.tracker.disconnect(info.trackerConnection); + } + + // Calls _addDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in desktop mode when dragging on the background. + _addDesktopDragGesture() { + // The SwipeTracker for switching workspaces in desktop mode is created here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L285 + const tracker = Main.wm._workspaceAnimation._swipeTracker; + let actor = Main.layoutManager._backgroundGroup; + const mode = Shell.ActionMode.NORMAL; + + // If not in the overview, you can usually only swipe to adjacent workspaces. This + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L633 + // allows us to override this behavior. + tracker.allowLongSwipes = true; + + // We have to make the background reactive. Make sure to store the current state so + // that we can reset it later. + this._origBackgroundReactivity = actor.reactive; + actor.reactive = true; + + this._desktopDragGesture = this._addDragGesture(actor, tracker, mode); + } + + // Calls _addDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in desktop mode when dragging on the panel. + _addPanelDragGesture() { + // The SwipeTracker for switching workspaces in desktop mode is created here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L285 + const tracker = Main.wm._workspaceAnimation._swipeTracker; + const actor = Main.panel; + const mode = Shell.ActionMode.NORMAL; + + // If not in the overview, you can usually only swipe to adjacent workspaces. This + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L633 + // allows us to override this behavior. + tracker.allowLongSwipes = true; + + // We have to prevent moving fullscreen windows when dragging. + this._origPanelTryDragWindow = actor._tryDragWindow; + actor._tryDragWindow = () => Clutter.EVENT_PROPAGATE; + + this._panelDragGesture = this._addDragGesture(actor, tracker, mode); + } + + // Calls _addDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in overview mode. + _addOverviewDragGesture() { + // The SwipeTracker for switching workspaces in overview mode is created here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L827 + const tracker = Main.overview._overview._controls._workspacesDisplay._swipeTracker; + const actor = Main.layoutManager.overviewGroup; + const mode = Shell.ActionMode.OVERVIEW; + + this._overviewDragGesture = this._addDragGesture(actor, tracker, mode); + } + + // Calls _removeDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in desktop mode when dragging on the background. + _removeDesktopDragGesture() { + if (this._desktopDragGesture) { + + // Restore original behavior. + this._desktopDragGesture.tracker.allowLongSwipes = false; + + // Make sure to restore the original state. + this._desktopDragGesture.actor.reactive = this._origBackgroundReactivity; + + this._removeDragGesture(this._desktopDragGesture); + + delete this._desktopDragGesture; + } + } + + // Calls _removeDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in desktop mode when dragging on the panel. + _removePanelDragGesture() { + if (this._panelDragGesture) { + + // Restore original behavior. + this._panelDragGesture.tracker.allowLongSwipes = false; + + // Make sure to restore the original state. + this._panelDragGesture.actor._tryDragWindow = this._origPanelTryDragWindow; + + this._removeDragGesture(this._panelDragGesture); + + delete this._panelDragGesture; + } + } + + // Calls _removeDragGesture() for the SwipeTracker and actor responsible for + // workspace-switching in overview mode. + _removeOverviewDragGesture() { + if (this._overviewDragGesture) { + this._removeDragGesture(this._overviewDragGesture); + + delete this._overviewDragGesture; + } + } +} + +// This function is called once when the extension is loaded, not enabled. +function init() { + return new Extension(); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..d1ad668 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..311e3c6 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..fd60468 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..11d681f Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..74507d1 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..7f872c1 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..1a5587d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..0c98267 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..a75b00d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..76ace22 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..53ce2bd Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..79cfaca Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..c4d9baf Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo new file mode 100644 index 0000000..3d5b191 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/metadata.json new file mode 100644 index 0000000..44b7e32 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/metadata.json @@ -0,0 +1,16 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Indulge in nostalgia with useless 3D effects.", + "gettext-domain": "desktop-cube", + "name": "Desktop Cube", + "settings-schema": "org.gnome.shell.extensions.desktop-cube", + "shell-version": [ + "40", + "41", + "42", + "43" + ], + "url": "https://github.com/Schneegans/Desktop-Cube", + "uuid": "desktop-cube@schneegans.github.com", + "version": 13 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/prefs.js new file mode 100644 index 0000000..135218e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/prefs.js @@ -0,0 +1,263 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const {Gio, Gtk, Gdk} = imports.gi; +const ByteArray = imports.byteArray; + +// libadwaita is available starting with GNOME Shell 42. +let Adw = null; +try { + Adw = imports.gi.Adw; +} catch (e) { + // Nothing to do. +} + +const _ = imports.gettext.domain('desktop-cube').gettext; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const utils = Me.imports.src.utils; +const ImageChooserButton = Me.imports.src.ImageChooserButton; + +////////////////////////////////////////////////////////////////////////////////////////// +// For now, the preferences dialog of this extension is very simple. In the future, if // +// we might consider to improve its layout... // +////////////////////////////////////////////////////////////////////////////////////////// + +var PreferencesDialog = class PreferencesDialog { + // ------------------------------------------------------------ constructor / destructor + + constructor() { + // Load all of our resources. + this._resources = Gio.Resource.load(Me.path + '/resources/desktop-cube.gresource'); + Gio.resources_register(this._resources); + + // Register our custom widgets. + ImageChooserButton.registerWidget(); + + // Load the user interface file. + this._builder = new Gtk.Builder(); + this._builder.add_from_resource(`/ui/settings.ui`); + + // Make sure custom icons are found. + Gtk.IconTheme.get_for_display(Gdk.Display.get_default()).add_resource_path('/img'); + + // This is our top-level widget which we will return later. Starting with GNOME Shell + // 42, the preferences window already has a built-in scrolled window. For older + // versions, we have to add this manually. + if (utils.shellVersionIsAtLeast(42)) { + this._widget = this._builder.get_object('settings-widget'); + } else { + this._widget = new Gtk.ScrolledWindow(); + + const box = this._builder.get_object('settings-widget'); + box.margin_start = 30; + box.margin_end = 30; + box.margin_top = 30; + box.margin_bottom = 30; + this._widget.set_child(box); + } + + // Store a reference to the settings object. + this._settings = ExtensionUtils.getSettings(); + + // Bind all properties. + this._bindAdjustment('workpace-separation'); + this._bindAdjustment('horizontal-stretch'); + this._bindAdjustment('window-parallax'); + this._bindImageChooserButton('background-panorama'); + this._bindSwitch('last-first-gap'); + this._bindSwitch('enable-desktop-dragging'); + this._bindSwitch('enable-panel-dragging'); + this._bindSwitch('enable-desktop-edge-switch'); + this._bindSwitch('enable-overview-edge-switch'); + this._bindSwitch('enable-overview-dragging'); + this._bindSwitch('do-explode'); + this._bindSwitch('per-monitor-perspective'); + this._bindAdjustment('active-workpace-opacity'); + this._bindAdjustment('inactive-workpace-opacity'); + this._bindAdjustment('edge-switch-pressure'); + this._bindAdjustment('mouse-rotation-speed'); + this._bindAdjustment('overview-transition-time'); + this._bindAdjustment('appgrid-transition-time'); + this._bindAdjustment('workspace-transition-time'); + + // Inject the video link. + const label = this._builder.get_object('multi-monitor-hint-label'); + label.label = label.label.replace( + '%s', 'https://youtu.be/dpYyn1BXGjU'); + + // Add a menu to the title bar of the preferences dialog. + this._widget.connect('realize', (widget) => { + const window = widget.get_root(); + + // Show the version number in the title bar. + window.title = `Desktop Cube ${Me.metadata.version}`; + + // Add the menu to the title bar + const menu = this._builder.get_object('menu-button'); + + // Starting with GNOME Shell 42, the settings dialog uses libadwaita (at least + // most of the time - it seems that pop!_OS does not support libadwaita even on + // GNOME 42). So we have to hack our way through the widget tree of the + // Adw.PreferencesWindow... + if (Adw && utils.shellVersionIsAtLeast(42)) { + const header = this._findWidgetByType(window.get_content(), Adw.HeaderBar); + header.pack_end(menu); + } else { + window.get_titlebar().pack_end(menu); + } + + // Populate the actions. + const group = Gio.SimpleActionGroup.new(); + + const addAction = (name, uri) => { + const action = Gio.SimpleAction.new(name, null); + action.connect('activate', () => Gtk.show_uri(null, uri, Gdk.CURRENT_TIME)); + group.add_action(action); + }; + + // clang-format off + addAction('homepage', 'https://github.com/Schneegans/Desktop-Cube'); + addAction('changelog', 'https://github.com/Schneegans/Desktop-Cube/blob/main/docs/changelog.md'); + addAction('translate', 'https://hosted.weblate.org/engage/desktop-cube/'); + addAction('bugs', 'https://github.com/Schneegans/Desktop-Cube/issues'); + addAction('donate-paypal', 'https://www.paypal.com/donate/?hosted_button_id=3F7UFL8KLVPXE'); + addAction('donate-github', 'https://github.com/sponsors/Schneegans'); + // clang-format on + + // Add the about dialog. + const aboutAction = Gio.SimpleAction.new('about', null); + aboutAction.connect('activate', () => { + // The JSON report format from weblate is a bit weird. Here we extract all + // unique names from the translation report. + const translators = new Set(); + this._getJSONResource('/credits/translators.json').forEach(i => { + for (const j of Object.values(i)) { + j.forEach(k => translators.add(k[1])); + } + }); + + const sponsors = this._getJSONResource('/credits/sponsors.json'); + + const dialog = new Gtk.AboutDialog({transient_for: window, modal: true}); + dialog.set_logo_icon_name('desktop-cube-symbolic'); + dialog.set_program_name(`Desktop-Cube ${Me.metadata.version}`); + dialog.set_website('https://github.com/Schneegans/Desktop-Cube'); + dialog.set_authors(['Simon Schneegans']); + dialog.set_copyright('© 2022 Simon Schneegans'); + dialog.set_translator_credits([...translators].join('\n')); + if (sponsors.gold.length > 0) { + dialog.add_credit_section(_('Gold Sponsors'), sponsors.gold); + } + if (sponsors.silver.length > 0) { + dialog.add_credit_section(_('Silver Sponsors'), sponsors.silver); + } + if (sponsors.bronze.length > 0) { + dialog.add_credit_section(_('Bronze Sponsors'), sponsors.bronze); + } + if (sponsors.past.length > 0) { + dialog.add_credit_section(_('Past Sponsors'), sponsors.past); + } + dialog.set_license_type(Gtk.License.GPL_3_0); + + dialog.show(); + }); + group.add_action(aboutAction); + + window.insert_action_group('prefs', group); + }); + + + // As we do not have something like a destructor, we just listen for the destroy + // signal of our main widget. + this._widget.connect('destroy', () => { + // Unregister our resources. + Gio.resources_unregister(this._resources); + }); + } + + // -------------------------------------------------------------------- public interface + + // Returns the widget used for the settings of this extension. + getWidget() { + return this._widget; + } + + // ----------------------------------------------------------------------- private stuff + + // Connects a DesktopCubeImageChooserButton (or anything else which has a 'file' + // property) to a settings key. It also binds the corresponding reset button. + _bindImageChooserButton(settingsKey) { + this._bind(settingsKey, 'file'); + } + + // Connects a Gtk.Adjustment (or anything else which has a 'value' property) to a + // settings key. It also binds the corresponding reset button. + _bindAdjustment(settingsKey) { + this._bind(settingsKey, 'value'); + } + + // Connects a Gtk.Switch (or anything else which has an 'active' property) to a settings + // key. It also binds the corresponding reset button. + _bindSwitch(settingsKey) { + this._bind(settingsKey, 'active'); + } + + // Connects any widget's property to a settings key. The widget must have the same ID as + // the settings key. It also binds the corresponding reset button. + _bind(settingsKey, property) { + this._settings.bind(settingsKey, this._builder.get_object(settingsKey), property, + Gio.SettingsBindFlags.DEFAULT); + + const resetButton = this._builder.get_object('reset-' + settingsKey); + resetButton.connect('clicked', () => { + this._settings.reset(settingsKey); + }); + } + + // Reads the contents of a JSON file contained in the global resources archive. The data + // is parsed and returned as a JavaScript object / array. + _getJSONResource(path) { + const data = Gio.resources_lookup_data(path, 0); + const string = ByteArray.toString(ByteArray.fromGBytes(data)); + return JSON.parse(string); + } + + // This traverses the widget tree below the given parent recursively and returns the + // first widget of the given type. + _findWidgetByType(parent, type) { + for (const child of [...parent]) { + if (child instanceof type) return child; + + const match = this._findWidgetByType(child, type); + if (match) return match; + } + + return null; + } +} + +// This is used for setting up the translations. +function init() { + ExtensionUtils.initTranslations(); +} + +// This function is called when the preferences window is created to build and return a +// Gtk widget. We create a new instance of the PreferencesDialog class each time this +// method is called. This way we can actually open multiple settings windows and interact +// with all of them properly. +function buildPrefsWidget() { + var dialog = new PreferencesDialog(); + return dialog.getWidget(); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource new file mode 100644 index 0000000..d305b40 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled new file mode 100644 index 0000000..ea0b3d2 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js new file mode 100644 index 0000000..ec1104b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js @@ -0,0 +1,317 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const {Clutter, GObject, Meta, Shell} = imports.gi; + +const Util = imports.misc.util; +const Main = imports.ui.main; +const ControlsState = imports.ui.overviewControls.ControlsState; +const Workspace = imports.ui.workspace.Workspace; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const utils = Me.imports.src.utils; + +////////////////////////////////////////////////////////////////////////////////////////// +// In GNOME Shell, SwipeTrackers are used all over the place to capture swipe gestures. // +// There's one for entering the overview, one for switching workspaces in desktop mode, // +// one for switching workspaces in overview mode, one for horizontal scrolling in the // +// app drawer, and many more. The ones used for workspace-switching usually do not // +// respond to single-click dragging but only to multi-touch gestures. We want to be // +// able to rotate the cube with the left mouse button, so we add the gesture defined // +// below to these two SwipeTracker instances (this is done by the _addDragGesture() of // +// the extension class). The gesture is loosely based on the gesture defined here: // +// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L213 // +// It behaves the same in the regard that it reports update events for horizontal // +// movements. However, it stores vertical movements as well and makes this accessible // +// via the "pitch" property. This is then used for vertical rotations of the cube. // +////////////////////////////////////////////////////////////////////////////////////////// + +const State = { + INACTIVE: 0, // The state will change to PENDING as soon as there is a mouse click. + PENDING: 1, // There was a click, but not enough movement to trigger the gesture. + ACTIVE: 2 // The gesture has been triggered and is in progress. +}; + +// clang-format off +var DragGesture = + GObject.registerClass({ + Properties: { + 'distance': GObject.ParamSpec.double( + 'distance', 'distance', 'distance', GObject.ParamFlags.READWRITE, 0, Infinity, 0), + 'pitch': GObject.ParamSpec.double( + 'pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, 0, 1, 0), + 'sensitivity': GObject.ParamSpec.double( + 'sensitivity', 'sensitivity', 'sensitivity', GObject.ParamFlags.READWRITE, 1, 10, 1), + }, + Signals: { + 'begin': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE]}, + 'update': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE]}, + 'end': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE]}, + }, + }, + class DragGesture extends GObject.Object { + // clang-format on + _init(actor, mode) { + super._init(); + + this._actor = actor; + this._state = State.INACTIVE; + this._mode = mode; + + // We listen to the 'captured-event' to be able to intercept some other actions. The + // main problem is the long-press action of the desktop background actor. This + // swallows any click events preventing us from dragging the desktop background. + // By connecting to 'captured-event', we have to extra-careful to propagate any event + // we are not interested in. + this._actorConnection1 = actor.connect('captured-event', (a, e) => { + return this._handleEvent(e); + }); + + // Once the input is grabbed, events are delivered directly to the actor, so we have + // also to connect to the normal "event" signal. + this._actorConnection2 = actor.connect('event', (a, e) => { + if (this._lastGrab) { + return this._handleEvent(e); + } + return Clutter.EVENT_PROPAGATE; + }); + } + + // Disconnects from the actor. + destroy() { + this._actor.disconnect(this._actorConnection1); + this._actor.disconnect(this._actorConnection2); + } + + // This is called on every captured event. + _handleEvent(event) { + + // Abort if the gesture is not meant for the current action mode (e.g. either + // Shell.ActionMode.OVERVIEW or Shell.ActionMode.NORMAL). + if (this._mode != Main.actionMode) { + return Clutter.EVENT_PROPAGATE; + } + + // In the overview, we only want to switch workspaces by dragging when in + // window-picker state. + if (Main.actionMode == Shell.ActionMode.OVERVIEW) { + if (Main.overview._overview.controls._stateAdjustment.value != + ControlsState.WINDOW_PICKER) { + return Clutter.EVENT_PROPAGATE; + } + } + + // Ignore touch events on X11. On X11, we get emulated pointer events. + if (!Meta.is_wayland_compositor() && + (event.type() == Clutter.EventType.TOUCH_BEGIN || + event.type() == Clutter.EventType.TOUCH_UPDATE || + event.type() == Clutter.EventType.TOUCH_END)) { + return Clutter.EVENT_PROPAGATE; + } + + // When a mouse button is pressed or a touch event starts, we store the corresponding + // position. The gesture is maybe triggered later, if the pointer was moved a little. + if (event.type() == Clutter.EventType.BUTTON_PRESS || + event.type() == Clutter.EventType.TOUCH_BEGIN) { + + // Here's a minor hack: In the overview, there are some draggable things like window + // previews which "compete" with this gesture. Sometimes, the cube is dragged, + // sometimes the window previews. So we make sure that we do only start the gesture + // for events which originate from the given actor or from a workspace's background. + if (Main.actionMode != Shell.ActionMode.OVERVIEW || + event.get_source() == this._actor || + event.get_source().get_parent() instanceof Workspace) { + this._clickPos = event.get_coords(); + this._state = State.PENDING; + } + + return Clutter.EVENT_PROPAGATE; + } + + // Abort the pending state if the pointer leaves the actor. + if (event.type() == Clutter.EventType.LEAVE && this._state == State.PENDING) { + this._cancel(); + return Clutter.EVENT_PROPAGATE; + } + + // As soon as the pointer is moved a bit, the drag action becomes active. + if (this._eventIsMotion(event)) { + + // If the mouse button is not pressed, we are not interested in the event. + if (this._state != State.INACTIVE && event.type() == Clutter.EventType.MOTION && + (event.get_state() & Clutter.ModifierType.BUTTON1_MASK) == 0) { + + this._cancel(); + return Clutter.EVENT_PROPAGATE; + } + + const currentPos = event.get_coords(); + + // If we are in the pending state, the gesture may be triggered as soon as the + // pointer is moved enough. + if (this._state == State.PENDING) { + + const threshold = Clutter.Settings.get_default().dnd_drag_threshold; + + if (Math.abs(currentPos[0] - this._clickPos[0]) > threshold || + Math.abs(currentPos[1] - this._clickPos[1]) > threshold) { + + + // When starting a drag in desktop mode, we grab the input so that we can move + // the pointer across windows without loosing the input events. + if (Main.actionMode == Shell.ActionMode.NORMAL) { + const sequence = event.type() == Clutter.EventType.TOUCH_UPDATE ? + event.get_event_sequence() : + null; + + if (!this._grab(event.get_device(), sequence)) { + return Clutter.EVENT_PROPAGATE; + } + } + + this._state = State.ACTIVE; + [this._lastX, this._startY] = currentPos; + this.pitch = 0; + this.emit('begin', event.get_time(), currentPos[0], currentPos[1]); + } + + // Even if the gesture started, we propagate the event so that any other + // gestures may wait for long-presses are canceled properly. + return Clutter.EVENT_PROPAGATE; + } + + // In the active state, we report updates on each movement. + if (this._state == State.ACTIVE) { + + // Compute the horizontal movement relative to the last call. + let deltaX = currentPos[0] - this._lastX; + this._lastX = currentPos[0]; + + // Compute the accumulated pitch relative to the screen height. + this.pitch = (this._startY - currentPos[1]) / global.screen_height; + + // Increase sensitivity. + deltaX *= this.sensitivity; + + // Increase horizontal movement if the cube is rotated vertically. + deltaX *= Util.lerp(1.0, global.workspaceManager.get_n_workspaces(), + Math.abs(this.pitch)); + + this.emit('update', event.get_time(), -deltaX, this.distance); + + return Clutter.EVENT_STOP; + } + + return Clutter.EVENT_PROPAGATE; + } + + // As soon as the mouse button is released or the touch event ends, we quit the + // gesture. + if (this._eventIsRelease(event)) { + + // If the gesture was active, report an end event. + if (this._state == State.ACTIVE) { + + this._cancel(); + + this.emit('end', event.get_time(), this.distance); + + return Clutter.EVENT_STOP; + } + + // If the gesture was in pending state, set it to inactive again. + this._cancel(); + + return Clutter.EVENT_PROPAGATE; + } + + return Clutter.EVENT_PROPAGATE; + } + + // This aborts any ongoing grab and resets the current state to inactive. + _cancel() { + if (this._lastGrab) { + this._ungrab(); + } + + this._state = State.INACTIVE; + } + + // Makes sure that all events from the pointing device we received last input from is + // passed to the given actor. This is used to ensure that we do not "loose" the touch + // buttons will dragging them around. + _grab(device, sequence) { + + // On GNOME Shell 42, there's a new API. + if (utils.shellVersionIsAtLeast(42)) { + this._lastGrab = global.stage.grab(this._actor); + return this._lastGrab != null; + } + + // Before, we needed to grab the device and enter modal mode. + if (global.begin_modal(0, 0)) { + if (sequence) { + device.sequence_grab(sequence, this._actor); + this._grabbedSequence = sequence; + } else { + device.grab(this._actor); + } + this._lastGrab = device; + return true; + } + + return false; + } + + // Releases a grab created with the method above. + _ungrab() { + if (utils.shellVersionIsAtLeast(42)) { + this._lastGrab.dismiss(); + } else { + if (this._grabbedSequence) { + this._lastGrab.sequence_ungrab(this._grabbedSequence); + this._grabbedSequence = null; + } else { + this._lastGrab.ungrab(); + } + global.end_modal(0); + } + this._lastGrab = null; + } + + // This is borrowed from here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dnd.js#L214 + _eventIsRelease(event) { + if (event.type() == Clutter.EventType.BUTTON_RELEASE) { + const buttonMask = Clutter.ModifierType.BUTTON1_MASK | + Clutter.ModifierType.BUTTON2_MASK | Clutter.ModifierType.BUTTON3_MASK; + // We only obey the last button release from the device, other buttons may get + // pressed / released during the drag. + return (event.get_state() & buttonMask) == 0; + } else if (event.type() == Clutter.EventType.TOUCH_END) { + // For touch, we only obey the pointer emulating sequence. + return global.display.is_pointer_emulating_sequence(event.get_event_sequence()); + } + + return false; + } + + // This is borrowed from here: + // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dnd.js#L259 + _eventIsMotion(event) { + return event.type() == Clutter.EventType.MOTION || + (event.type() == Clutter.EventType.TOUCH_UPDATE && + global.display.is_pointer_emulating_sequence(event.get_event_sequence())); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js new file mode 100644 index 0000000..19aaec0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const {GObject, Gtk, Gio} = imports.gi; + +const _ = imports.gettext.domain('desktop-cube').gettext; + +////////////////////////////////////////////////////////////////////////////////////////// +// This is based on a similar class from the Fly-Pie extension (MIT License). // +// https://github.com/Schneegans/Fly-Pie/blob/main/src/prefs/ImageChooserButton.js // +// We only need file chooser buttons for images, so the content. // +////////////////////////////////////////////////////////////////////////////////////////// + +function registerWidget() { + + if (GObject.type_from_name('DesktopCubeImageChooserButton') == null) { + GObject.registerClass( + { + GTypeName: 'DesktopCubeImageChooserButton', + Template: `resource:///ui/imageChooserButton.ui`, + InternalChildren: ['button', 'label'], + Properties: { + 'file': GObject.ParamSpec.string('file', 'file', 'file', + GObject.ParamFlags.READWRITE, ''), + }, + }, + class DesktopCubeImageChooserButton extends Gtk.Box { // -------------------------- + _init(params = {}) { + super._init(params); + + this._dialog = new Gtk.Dialog({use_header_bar: true, modal: true, title: ''}); + this._dialog.add_button(_('Select File'), Gtk.ResponseType.OK); + this._dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); + this._dialog.set_default_response(Gtk.ResponseType.OK); + + const fileFilter = new Gtk.FileFilter(); + fileFilter.add_mime_type('image/*'); + + this._fileChooser = new Gtk.FileChooserWidget({ + action: Gtk.FileChooserAction.OPEN, + hexpand: true, + vexpand: true, + height_request: 500, + filter: fileFilter + }); + + this._dialog.get_content_area().append(this._fileChooser); + + this._dialog.connect('response', (dialog, id) => { + if (id == Gtk.ResponseType.OK) { + this.file = this._fileChooser.get_file().get_path(); + } + dialog.hide(); + }); + + this._button.connect('clicked', (button) => { + this._dialog.set_transient_for(button.get_root()); + + this._dialog.show(); + + if (this._file != null) { + this._fileChooser.set_file(this._file); + } + }); + } + + // Returns the currently selected file. + get file() { + return this._file.get_path(); + } + + // This makes the file chooser dialog preselect the given file. + set file(value) { + this._file = Gio.File.new_for_path(value); + + if (this._file.query_exists(null)) { + this._label.label = this._file.get_basename(); + } else { + this._label.label = _('(None)'); + this._file = null; + } + + this.notify('file'); + } + }); + } +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/Skybox.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/Skybox.js new file mode 100644 index 0000000..2f78619 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/Skybox.js @@ -0,0 +1,154 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const {Clutter, GObject, GdkPixbuf, Cogl, Shell} = imports.gi; + +const Main = imports.ui.main; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const utils = Me.imports.src.utils; + +////////////////////////////////////////////////////////////////////////////////////////// +// This file contains two classes, the Skybox (which is an actor) and the SkyboxEffect, // +// which is a Shell.GLSLEffect which is applied to the Skybox actor. // +// // +// SkyboxEffect loads a given texture and interprets it as a 360° panorama in // +// equirectangular projection. It uses the current perspective of the stage to draw a // +// perspectively correct portion of this panorama. It has an additional pitch and yaw // +// parameter controlling the horizontal and vertical rotation of the camera. // +////////////////////////////////////////////////////////////////////////////////////////// + +// clang-format off +var SkyboxEffect = GObject.registerClass({ + Properties: { + 'yaw': GObject.ParamSpec.double('yaw', 'yaw', 'yaw', GObject.ParamFlags.READWRITE, + -2 * Math.PI, 2 * Math.PI, 0), + 'pitch': GObject.ParamSpec.double('pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, + -0.5 * Math.PI, 0.5 * Math.PI, 0), + }, + }, class SkyboxEffect extends Shell.GLSLEffect { + // clang-format on + _init(file) { + super._init(); + + const FORMATS = [ + Cogl.PixelFormat.G_8, + Cogl.PixelFormat.RG_88, + Cogl.PixelFormat.RGB_888, + Cogl.PixelFormat.RGBA_8888, + ]; + + // Attempt to load the texture. + const textureData = GdkPixbuf.Pixbuf.new_from_file(file); + this._texture = new Clutter.Image(); + this._texture.set_data(textureData.get_pixels(), + FORMATS[textureData.get_n_channels() - 1], textureData.width, + textureData.height, textureData.rowstride); + + // Redraw if either the pitch or the yaw changes. + this.connect('notify::yaw', () => {this.queue_repaint()}); + this.connect('notify::pitch', () => {this.queue_repaint()}); + }; + + // This is called once to setup the Cogl.Pipeline. + vfunc_build_pipeline() { + + // In the vertex shader, we compute the view space position of the actor's corners. + this.add_glsl_snippet(Shell.SnippetHook.VERTEX, 'varying vec4 vsPos;', + 'vsPos = cogl_modelview_matrix * cogl_position_in;', false); + + const fragmentDeclares = ` + varying vec4 vsPos; + uniform sampler2D uTexture; + uniform float uPitch; + uniform float uYaw; + + mat3 getPitch() { + float s = sin(uPitch); + float c = cos(uPitch); + return mat3(1.0, 0.0, 0.0, 0.0, c, s, 0.0, -s, c); + } + + mat3 getYaw() { + float s = sin(uYaw); + float c = cos(uYaw); + return mat3(c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c); + } + `; + + // The fragment shader uses the interpolated viewspace position to compute a view + // ray. This ray is rotated according to the pitch and yaw values. + const fragmentCode = ` + // Rotate the view ray. + vec3 view = getYaw() * getPitch() * normalize(vsPos.xyz); + + // Compute equirectangular projection. + const float pi = 3.14159265359; + float x = 0.5 + 0.5 * atan(view.x, -view.z) / pi; + float y = acos(view.y) / pi; + + cogl_color_out = texture2D(uTexture, vec2(x, y)); + `; + + this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, fragmentDeclares, fragmentCode, + false); + } + + // For each draw call, we have to set some uniform values. + vfunc_paint_target(node, paintContext) { + this.get_pipeline().set_layer_texture(0, this._texture.get_texture()); + + this.set_uniform_float(this.get_uniform_location('uTexture'), 1, [0]); + this.set_uniform_float(this.get_uniform_location('uPitch'), 1, [this.pitch]); + this.set_uniform_float(this.get_uniform_location('uYaw'), 1, [this.yaw]); + + super.vfunc_paint_target(node, paintContext); + } +}); + +////////////////////////////////////////////////////////////////////////////////////////// +// The Skybox is a simple actor which applies the above effect to itself. It also has // +// the pitch and yaw properties - these are directly forwarded to the effect. // +////////////////////////////////////////////////////////////////////////////////////////// + +// clang-format off +var Skybox = GObject.registerClass({ + Properties: { + 'yaw': GObject.ParamSpec.double('yaw', 'yaw', 'yaw', GObject.ParamFlags.READWRITE, + -2 * Math.PI, 2 * Math.PI, 0), + 'pitch': GObject.ParamSpec.double('pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, + -0.5 * Math.PI, 0.5 * Math.PI, 0), + } + }, class Skybox extends Clutter.Actor { + // clang-format on + _init(file) { + super._init(); + + // Apply the effect. + this._effect = new SkyboxEffect(file); + this.add_effect(this._effect); + + // Make sure that the overview background is transparent. + Main.uiGroup.add_style_class_name('desktop-cube-panorama-enabled'); + + // Forward the yaw and pitch values. + this.bind_property('yaw', this._effect, 'yaw', GObject.BindingFlags.NONE); + this.bind_property('pitch', this._effect, 'pitch', GObject.BindingFlags.NONE); + + // Revert to the original overview background appearance. + this.connect('destroy', () => { + Main.uiGroup.remove_style_class_name('desktop-cube-panorama-enabled'); + }); + } +}); \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/utils.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/utils.js new file mode 100644 index 0000000..956c1ae --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/src/utils.js @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // +// | \ | ( ` | / | / \ | ) / | | | ) | // +// | | |- `-. |< | | | |-' | | | |-< |- // +// | / | . ) | \ | \ / | \ | | | ) | // +// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const Config = imports.misc.config; +const [GS_MAJOR] = Config.PACKAGE_VERSION.split('.'); + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); + +// This method can be used to write a message to GNOME Shell's log. This is enhances +// the standard log() functionality by prepending the extension's name and the location +// where the message was logged. As the extensions name is part of the location, you +// can more effectively watch the log output of GNOME Shell: +// journalctl -f -o cat | grep -E 'desktop-cube|' +// This method is based on a similar script from the Fly-Pie GNOME Shell extension which +// os published under the MIT License (https://github.com/Schneegans/Fly-Pie). +function debug(message) { + const stack = new Error().stack.split('\n'); + + // Remove debug() function call from stack. + stack.shift(); + + // Find the index of the extension directory (e.g. desktopcube@schneegans.github.com) + // in the stack entry. We do not want to print the entire absolute file path. + const extensionRoot = stack[0].indexOf(Me.metadata.uuid); + + log('[' + stack[0].slice(extensionRoot) + '] ' + message); +} + +// This method returns true if the current GNOME Shell version matches the given +// argument. +function shellVersionIs(major) { + return GS_MAJOR == major; +} + +// This method returns true if the current GNOME Shell version is at least as high as the +// given argument. +function shellVersionIsAtLeast(major) { + return GS_MAJOR >= major; +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/stylesheet.css new file mode 100644 index 0000000..82ed00c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/desktop-cube@schneegans.github.com/stylesheet.css @@ -0,0 +1,20 @@ +/* +SPDX-FileCopyrightText: Simon Schneegans +SPDX-License-Identifier: CC0-1.0 +*/ + +/* +This ensures that the overview background is transparent, so that the background +panorama becomes visible. +*/ +.desktop-cube-panorama-enabled #overviewGroup { + background: transparent; +} + +/* +This ensures that the background during workspace switches becomes transparent, so that +the background panorama becomes visible. +*/ +.desktop-cube-panorama-enabled .workspace-animation { + background-color: transparent; +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md new file mode 100644 index 0000000..d2467b4 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md @@ -0,0 +1,420 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +We go to the next version after each release on [GNOME Shell Extensions website](https://extensions.gnome.org/). + +## [Unreleased] + +## [22.0.0 Millet] - 2022-09-10 + +### Fixed + +- Dash app button visibility height. +- Looking glass error after unlock. + +### Added + +- App menu label visibility. +- GNOME Shell 43 support. +- Quick settings menu visibility. + +### Removed + +- Aggregate menu for GNOME Shell 43 and higher. + +## [21.0.0 Reynolds] - 2022-08-06 + +### Changed + +- Prefs compatibility layer checking to GTK and Adw instead of GNOME Shell version. + +### Fixed + +- Application button visibility in Ubuntu 22.04. +- Prefs window size for scaled displays. +- Prefs window size for small displays in GNOME Shell 42. +- Racy prefs window size. +- Window caption going out of display area when dash is disabled in GNOME Shell 40 and higher. +- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). +- Spanish translation by [@Luci](https://gitlab.gnome.org/Luci). + +### Added + +- Alt Tab window preview icon size. +- Alt Tab window preview size. +- Alt Tab icon size. +- Dash separator visibility. +- Looking glass size by [@AdvendraDeswanta](https://gitlab.gnome.org/AdvendraDeswanta). +- OSD position. +- Take screenshot button in window menu visibility. + +### Removed + +- Gesture API for GNOME Shell 40 and higher. +- List box separators for GNOME Shell 40 and 41 (EOS). +- Prefs intro. + +## [20.0.0 Hayez] - 2022-04-01 + +### Fixed + +- Dynamic workspaces getting disabled by workspace popup. +- Flickering panel after Unlock. +- Notification banner position on GNOME Shell 42. +- Window demands attention focus on GNOME Shell 42. +- French translation by [@GeoffreyCoulaud](https://gitlab.gnome.org/GeoffreyCoulaud). +- Italian translation by [@svityboy](https://gitlab.gnome.org/svityboy). + +### Added + +- Events visibility in clock menu. +- Calendar visibility in clock menu. +- Dutch translation by [@Vistaus](https://gitlab.gnome.org/Vistaus). + +## [19.0.0 Ancher] - 2022-03-02 + +### Fixed + +- Blurry search entry on GNOME Shell themes with box-shadow. +- Prefs file chooser recursion. +- SecondaryMonitorDisplay error on GNOME Shell 42. +- Shell theme override OSD for GNOME Shell 42. +- Shell theme override workspace switcher for GNOME Shell 42. +- Workspace popup visiblity in GNOME Shell 42. + +### Added + +- Libadwaita for GNOME Shell 42 prefs. +- Panel icon size. +- Panel world clock visiblity. +- Weather visiblity. + +## [18.0.0 Roslin] - 2022-02-12 + +### Fixed + +- GNOME 3.x prefs error. + +## [17.0.0 Roslin] - 2022-02-11 + +### Fixed + +- Emitting panel show when panel is visible. +- Looking glass not showing up. +- Looking glass position on startup when panel is hidden. +- Prefs height going off the screen in small displays. +- Prefs lunching url freeze on Wayland. +- Prefs padding in GNOME Shell 42. +- Prefs UI Improvement by [@muqtxdir](https://gitlab.gnome.org/muqtxdir). +- Startup animation for hiding panel when panel is disabled. +- Type to search when text entry content is replaced with another content. +- Window goes under panel after unlock on Wayland. +- Window picker caption visibility issue on Pop Shell. +- Galician translation by [@frandieguez](https://gitlab.gnome.org/frandieguez). + +### Added + +- Bottom to notification banner position. + +### Removed + +- Panel corner size option for GNOME Shell 42. + +## [16.0.0 Rembrandt] - 2021-11-15 + +### Fixed + +- Animation jump when search entry is disabled and entering app grid. +- Clock menu revealing in lockscreen when the position is left or right. +- Startup status for Ubuntu. +- Workspace switcher visiblity in GNOME Shell 41. + +### Removed + +- Hot corner for GNOME Shell 41. +- Hot corner library for all supported Shell versions. + +### Added + +- Double supper to app grid for GNOME Shell 40 and 41. +- Panel corner size when panel is disabled. +- Panel visiblity in overview when panel is disabled. +- Prefs window intro. +- Profile selector to the prefs window. +- Ripple box. + +## [15.0.0 Magnetized] - 2021-09-22 + +### Fixed + +- unlock recursion error. + +### Added + +- Hot corner support for GNOME Shell 41. + +## [14.0.0 Magnetized] - 2021-09-22 + +### Changed + +- Repo folder structure to have better organization. + +### Fixed + +- Bottom panel position for multi monitors [@harshadgavali](https://gitlab.gnome.org/harshadgavali). +- First swipe up in desktop startup status. +- Looking glass position on bottom panel. +- Maximized window gap on Wayland. +- Search entry animation for type to search when search entry is disabled. +- Search entry API to avoid conflicting with other extensions. +- Window picker caption border on disable. +- Window picker disapearing on wayland with shell theme override. +- Galician translation by [@frandieguez](https://gitlab.gnome.org/frandieguez). +- Spanish translation by [@DiegoIvanME](https://gitlab.gnome.org/DiegoIvanME). + +### Removed + +- Donation popover in prefs. +- Hot corner for GNOME Shell 41. + +### Added + +- GNOME Shell 41 support. +- Panel indicator padding size. +- Window picker close button visibility. + +## [13.0.0 Ring] - 2021-08-10 + +### Changed + +- Search button position in prefs window. + +### Fixed + +- Accessing dash in case the original dash has been removed by third party extensions. +- API.monitorGetInfo for "pMonitor is null" error. +- Dropdown align in preferences dialog. +- Startup status blocking shortcut keys. +- Unwanted window demands attention focus. +- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). + +### Removed + +- Settings and Translation library and using ExtensionUtils instead. + +### Added + +- Panel button padding size. +- Panel height. +- Window picker caption visibility. +- Workspace background corner size in overview. +- Workspace wraparound (modified version of WorkspaceSwitcherWrapAround by [@war1025](https://github.com/war1025)). + +## [12.0.0 Queen Red] - 2021-06-29 + +### Changed + +- Lighter background color for switcher list (alt+tab) in override theme. +- Workspace switcher max size now maxed out to 30%. + +### Fixed + +- Combobox scroll issue on GTK4. +- Window demands attention focus notification popup. +- French translation by [@GeoffreyCoulaud](https://gitlab.gnome.org/GeoffreyCoulaud). +- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). + +### Added + +- Always show workspace switcher on dynamic workspaces. +- More descriptions to the preferences dialog. +- Notification banner position. +- Startup status for GNOME Shell 40. +- Workspace animation background color for shell theme override. +- Workspaces visiblity in app grid by [@fmuellner](https://gitlab.gnome.org/fmuellner). +- Chinese (Taiwan) translation by [@r0930514](https://gitlab.com/r0930514). + +## [11.0.0 Whisper] - 2021-05-20 + +### Changed + +- App gesture now only works on GNOME 3.36 and 3.38. +- Donation icon to GTK4 non-compatible icon sets. +- Shell theme override is now disabled by default. +- Workspace switcher size for GNOME Shell 40 is now maxed out to 15%. + +### Fixed + +- Gap when panel posision is at the bottom and shell override theme happens. +- Panel menu margin when panel is in bottom. +- Window picker icon visiblity on drag. +- Workspace switcher size for multi monitor setup. +- Arabic translation by [@AliGalal](https://gitlab.com/AliGalal). +- Chinese translation by [@wsxy162](https://gitlab.com/wsxy162). +- Italian translation by [@l3nn4rt](https://gitlab.com/l3nn4rt). +- Swedish translation by [@MorganAntonsson](https://gitlab.com/MorganAntonsson). + +### Added + +- Activities button icon. +- Dash icon size. +- Window demands attention focus. + +## [10.0.0] - 2021-03-26 + +### Changed + +- Organized prefs UI for icons and behavior. +- Removed quotes and side bar image from prefs UI. + +### Fixed + +- Fake hot corner primary monitor position. +- Horizontal scroll in prefs. +- Primary Monitor Panel Position. +- Arabic translation by [@karem34](https://gitlab.com/karem34). +- Russian translation by [@librusekus35790](https://gitlab.com/librusekus35790). + +### Added + +- Clock menu position. +- Disable animation or change the animation speed. +- Disable applications button in dash. +- Disable app menu icon. +- Disable panel arrow in GNOME 3.36 and 3.38. +- Disable panel notification icon. +- No results found for prefs window. +- Brazilian Portuguese translation by [@Zelling](https://gitlab.com/Zelling). +- Catalan translation by [@juxuanu](https://gitlab.com/juxuanu). +- Galician translation by [@frandieguez](https://gitlab.com/frandieguez). + +## [9.0.0] - 2021-03-06 + +### Changed + +- Prefs interface. + +### Fixed + +- Default value for hot corner on extension disable. +- GNOME Shell 40.beta version. + +### Added + +- Disable power icon. +- Panel position. +- Support to prefs window. + +## [8.0.0] - 2021-02-22 + +### Changed + +- Holding back lonely overview until the final GNOME 40 release. + +### Fixed + +- Dash override theme on GNOME Shell 40 beta. +- Focus for find entry on prefs. +- Search controller for GNOME Shell 40 beta. +- Start search for GNOME Shell 40 beta. +- Workspace switcher enable related to workspace switcher size. +- Nepali translation filename by [@IBA4](https://gitlab.com/IBA4). + +## [7.0.0] - 2021-02-12 + +### Fixed + +- GNOME Shell 40 hidden side by side workspace preview. +- GNOME Shell 40 search padding when panel is disabled. +- Initial prefs window size. + +### Added + +- GNOME Shell 40 window picker icon visibility to the settings. +- GNOME Shell 40 workspace switcher size to the settings. +- Panel corner size to the settings. +- Search feature to the settings. +- Type to Search to the settings. +- Nepali translation by [@IBA4](https://gitlab.com/IBA4). +- Spanish translation by [@oscfdezdz](https://gitlab.com/oscfdezdz). + +## [6.0.0] - 2021-01-29 + +### Fixed + +- GNOME Shell 3.38 extra padding on no workspace switcher. +- GNOME Shell 40 and GTK4 support for prefs. +- GNOME Shell 40 support for search entry. +- GNOME Shell 40 support for workspace switcher. + +## [5.0.0] - 2021-01-05 + +### Added + +- Accessibility Menu visibility to the settings. +- Activities button visibility to the settings. +- App menu visibility to the settings. +- Clock menu visibility to the settings. +- Keyboard Layout visibility to the settings. +- System Menu (Aggregate Menu) visibility to the settings. + +### Changed + +- OSD in settings to "On Screen Display (OSD)". + +### Fixed + +- Hot corner when top panel is visible. +- Padding on no dash. +- Search top padding on no top panel. + +## [4.0.0] 2020-12-25 + +### Added + +- API to decouple all libraries from using GNOME Shell ui directly. +- Automate build process by [@daPhipz](https://gitlab.com/daPhipz). +- CHANGELOG.md file. +- Compatibility layer for API. +- Translation automation script by [@daPhipz](https://gitlab.com/daPhipz). + +### Changed + +- Default settings to enable. +- Displaying error for generate-mo.sh by [@daPhipz](https://gitlab.com/daPhipz). +- German translation by [@M4he](https://gitlab.com/M4he). + +### Fixed + +- Top padding on no search and no top panel. + +## [3.0.0] - 2020-12-21 + +### Added + +- CONTRIBUTING.md file. +- Decoupled library from GNOME Shell ui. +- Extension logo. +- Initial Translations. +- Prefs as extension settings. + +## [2.0.0] - 2020-11-18 + +### Fixed + +- Destroy hot corner on disable. + +## [1.0.0] - 2020-11-15 + +### Added + +- Disable app gesture. +- Disable background menu. +- Hide dash. +- Hide search. +- Hide top panel. +- Hide workspace switcher. +- Hot corner to toggle overview visibility. + +. diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/LICENSE b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/LICENSE new file mode 100644 index 0000000..ce02513 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/LICENSE @@ -0,0 +1,675 @@ + 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. + + Just Perfection GNOME Shell Desktop + Copyright (C) 2020-2022 Javad Rahmatzadeh + + 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: + + Just Perfection GNOME Shell Desktop + Copyright (C) 2020-2022 Javad Rahmatzadeh + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/bin/close-button.svg b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/bin/close-button.svg new file mode 100644 index 0000000..c4a62ba --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/bin/close-button.svg @@ -0,0 +1,50 @@ + +Close Buttonimage/svg+xmlClose ButtonJavad RahmatzadehJavad Rahmatzadeh2022 diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/extension.js new file mode 100644 index 0000000..f5eec62 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/extension.js @@ -0,0 +1,121 @@ +/** + * Extension + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +const {API, Manager} = Me.imports.lib; +const {GObject, GLib, Gio, St, Clutter, Meta} = imports.gi; + +const Util = imports.misc.util; +const Config = imports.misc.config; +const shellVersion = parseFloat(Config.PACKAGE_VERSION); + +const Main = imports.ui.main; +const BackgroundMenu = imports.ui.backgroundMenu; +const OverviewControls = imports.ui.overviewControls; +const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; +const ViewSelector = (shellVersion < 40) ? imports.ui.viewSelector : null; +const WorkspaceThumbnail = imports.ui.workspaceThumbnail; +const SearchController = (shellVersion >= 40) ? imports.ui.searchController : null; +const Panel = imports.ui.panel; +const WorkspacesView = imports.ui.workspacesView; +const WindowPreview = (shellVersion >= 3.38) ? imports.ui.windowPreview : null; +const Workspace = imports.ui.workspace; +const LookingGlass = imports.ui.lookingGlass; +const MessageTray = imports.ui.messageTray; +const OSDWindow = imports.ui.osdWindow; +const WindowMenu = imports.ui.windowMenu; +const AltTab = imports.ui.altTab; + +let manager; +let api; + +/** + * initiate extension + * + * @returns {void} + */ +function init() +{ +} + +/** + * enable extension + * + * @returns {void} + */ +function enable() +{ + // <3.36 can crash by enabling the extension + // since <3.36 is not supported we simply return + // to avoid bad experience for <3.36 users. + if (shellVersion < 3.36) { + return; + } + + let InterfaceSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.interface'}); + + api = new API.API({ + Main, + BackgroundMenu, + OverviewControls, + WorkspaceSwitcherPopup, + InterfaceSettings, + SearchController, + ViewSelector, + WorkspaceThumbnail, + WorkspacesView, + Panel, + WindowPreview, + Workspace, + LookingGlass, + MessageTray, + OSDWindow, + WindowMenu, + AltTab, + St, + Gio, + GLib, + Clutter, + Util, + Meta, + GObject, + }, shellVersion); + + api.open(); + + let settings = ExtensionUtils.getSettings(); + + manager = new Manager.Manager({ + API: api, + Settings: settings, + }, shellVersion); + + manager.registerSettingsSignals(); + manager.applyAll(); +} + +/** + * disable extension + * + * @returns {void} + */ +function disable() +{ + if (manager) { + manager.revertAll(); + manager = null; + } + + if (api) { + api.close(); + api = null; + } +} + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/API.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/API.js new file mode 100644 index 0000000..61a4639 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/API.js @@ -0,0 +1,3354 @@ +/** + * API Library + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +const XY_POSITION = { + TOP_START: 0, + TOP_CENTER: 1, + TOP_END: 2, + BOTTOM_START: 3, + BOTTOM_CENTER: 4, + BOTTOM_END: 5, + CENTER_START: 6, + CENTER_CENTER: 7, + CENTER_END: 8, +}; + +const PANEL_POSITION = { + TOP: 0, + BOTTOM: 1, +}; + +const PANEL_BOX_POSITION = { + CENTER: 0, + RIGHT: 1, + LEFT: 2, +}; + +const PANEL_HIDE_MODE = { + ALL: 0, + DESKTOP: 1, +}; + +const SHELL_STATUS = { + NONE: 0, + OVERVIEW: 1, +}; + +const ICON_TYPE = { + NAME: 0, + URI: 1, +}; + +const DASH_ICON_SIZES = [16, 22, 24, 32, 48, 64]; + +/** + * API to avoid calling GNOME Shell directly + * and make all parts compatible with different GNOME Shell versions + */ +var API = class +{ + /** + * Class Constructor + * + * @param {Object} dependencies + * 'Main' reference to ui::main + * 'BackgroundMenu' reference to ui::backgroundMenu + * 'OverviewControls' reference to ui::overviewControls + * 'WorkspaceSwitcherPopup' reference to ui::workspaceSwitcherPopup + * 'InterfaceSettings' reference to Gio::Settings for 'org.gnome.desktop.interface' + * 'SearchController' reference to ui::searchController + * 'ViewSelector' reference to ui::viewSelector + * 'WorkspaceThumbnail' reference to ui::workspaceThumbnail + * 'WorkspacesView' reference to ui::workspacesView + * 'Panel' reference to ui::panel + * 'WindowPreview' reference to ui::windowPreview + * 'Workspace' reference to ui::workspace + * 'LookingGlass' reference to ui::lookingGlass + * 'MessageTray' reference to ui::messageTray + * 'OSDWindow' reference to ui::osdTray + * 'WindowMenu' reference to ui::windowMenu + * 'AltTab' reference to ui::altTab + * 'St' reference to St + * 'Gio' reference to Gio + * 'GLib' reference to GLib + * 'Clutter' reference to Clutter + * 'Util' reference to misc::util + * 'Meta' reference to Meta + * 'GObject' reference to GObject + * @param {number} shellVersion float in major.minor format + */ + constructor(dependencies, shellVersion) + { + this._main = dependencies['Main'] || null; + this._backgroundMenu = dependencies['BackgroundMenu'] || null; + this._overviewControls = dependencies['OverviewControls'] || null; + this._workspaceSwitcherPopup = dependencies['WorkspaceSwitcherPopup'] || null; + this._interfaceSettings = dependencies['InterfaceSettings'] || null; + this._searchController = dependencies['SearchController'] || null; + this._viewSelector = dependencies['ViewSelector'] || null; + this._workspaceThumbnail = dependencies['WorkspaceThumbnail'] || null; + this._workspacesView = dependencies['WorkspacesView'] || null; + this._panel = dependencies['Panel'] || null; + this._windowPreview = dependencies['WindowPreview'] || null; + this._workspace = dependencies['Workspace'] || null; + this._lookingGlass = dependencies['LookingGlass'] || null; + this._messageTray = dependencies['MessageTray'] || null; + this._osdWindow = dependencies['OSDWindow'] || null; + this._windowMenu = dependencies['WindowMenu'] || null; + this._altTab = dependencies['AltTab'] || null; + this._st = dependencies['St'] || null; + this._gio = dependencies['Gio'] || null; + this._glib = dependencies['GLib'] || null; + this._clutter = dependencies['Clutter'] || null; + this._util = dependencies['Util'] || null; + this._meta = dependencies['Meta'] || null; + this._gobject = dependencies['GObject'] || null; + + this._shellVersion = shellVersion; + this._originals = {}; + this._timeoutIds = {}; + + /** + * whether search entry is visible + * + * @member {boolean} + */ + this._searchEntryVisibility = true; + + /** + * last workspace switcher size in float + * + * @member {number} + */ + this._workspaceSwitcherLastSize + = (this._workspaceThumbnail && this._shellVersion >= 40) + ? this._workspaceThumbnail.MAX_THUMBNAIL_SCALE + : 0.0; + } + + /** + * prepare everything needed for API + * + * @returns {void} + */ + open() + { + this.UIStyleClassAdd(this._getAPIClassname('shell-version')); + } + + /** + * remove everything from GNOME Shell been added by this class + * + * @returns {void} + */ + close() + { + this.UIStyleClassRemove(this._getAPIClassname('shell-version')); + this._startSearchSignal(false); + + for (let [name, id] of Object.entries(this._timeoutIds)) { + this._glib.source_remove(id); + delete(this._timeoutIds[name]); + } + } + + /** + * get x and y align for position + * + * @param int pos position + * see XY_POSITION + * + * @returns {array} + * - 0 Clutter.ActorAlign + * - 1 Clutter.ActorAlign + */ + _xyAlignGet(pos) + { + if (XY_POSITION.TOP_START === pos) { + return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.START]; + } + + if (XY_POSITION.TOP_CENTER === pos) { + return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.START]; + } + + if (XY_POSITION.TOP_END === pos) { + return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.START]; + } + + if (XY_POSITION.CENTER_START === pos) { + return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.CENTER]; + } + + if (XY_POSITION.CENTER_CENTER === pos) { + return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.CENTER]; + } + + if (XY_POSITION.CENTER_END === pos) { + return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.CENTER]; + } + + if (XY_POSITION.BOTTOM_START === pos) { + return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.END]; + } + + if (XY_POSITION.BOTTOM_CENTER === pos) { + return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.END]; + } + + if (XY_POSITION.BOTTOM_END === pos) { + return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.END]; + } + } + + /** + * add to animation duration + * + * @param {number} duration in milliseconds + * + * @returns {number} + */ + _addToAnimationDuration(duration) + { + let settings = this._st.Settings.get(); + + return (settings.enable_animations) ? settings.slow_down_factor * duration : 1; + } + + /** + * get signal id of the event + * + * @param {Gtk.Widget} widget to find signal in + * @param {string} signalName signal name + * + * @returns {number} + */ + _getSignalId(widget, signalName) + { + return this._gobject.signal_handler_find(widget, { signalId: signalName }); + } + + /** + * get the css classname for API + * + * @param {string} type possible types + * shell-version + * no-search + * no-workspace + * no-panel + * panel-corner + * no-window-picker-icon + * type-to-search + * no-power-icon + * bottom-panel + * no-panel-arrow + * no-panel-notification-icon + * no-app-menu-icon + * no-app-menu-label + * no-show-apps-button + * activities-button-icon + * activities-button-icon-monochrome + * activities-button-no-label + * dash-icon-size + * panel-button-padding-size + * panel-indicator-padding-size + * no-window-caption + * workspace-background-radius-size + * no-window-close + * refresh-styles + * no-ripple-box + * no-weather + * no-world-clocks + * panel-icon-size + * no-events-button + * osd-position-top + * osd-position-bottom + * osd-position-center + * no-dash-separator + * + * @returns {string} + */ + _getAPIClassname(type) + { + let starter = 'just-perfection-api-'; + + let possibleTypes = [ + 'shell-version', + 'no-search', + 'no-workspace', + 'no-panel', + 'panel-corner', + 'no-window-picker-icon', + 'type-to-search', + 'no-power-icon', + 'bottom-panel', + 'no-panel-arrow', + 'no-panel-notification-icon', + 'no-app-menu-icon', + 'no-app-menu-label', + 'no-show-apps-button', + 'activities-button-icon', + 'activities-button-icon-monochrome', + 'activities-button-no-label', + 'dash-icon-size', + 'panel-button-padding-size', + 'panel-indicator-padding-size', + 'no-window-caption', + 'workspace-background-radius-size', + 'no-window-close', + 'refresh-styles', + 'no-ripple-box', + 'no-weather', + 'no-world-clocks', + 'panel-icon-size', + 'no-events-button', + 'osd-position-top', + 'osd-position-bottom', + 'osd-position-center', + 'no-dash-separator', + ]; + + if (!possibleTypes.includes(type)) { + return ''; + } + + if (type === 'shell-version') { + let shellVerMajor = Math.trunc(this._shellVersion); + return `${starter}gnome${shellVerMajor}`; + } + + return starter + type; + } + + /** + * allow shell theme use its own panel corner + * + * @returns {void} + */ + panelCornerSetDefault() + { + if (this._shellVersion >= 42) { + return; + } + + let classnameStarter = this._getAPIClassname('panel-corner'); + + for (let size = 0; size <= 60; size++) { + this.UIStyleClassRemove(classnameStarter + size); + } + } + + /** + * change panel corner size + * + * @param {number} size 0 to 60 + * + * @returns {void} + */ + panelCornerSetSize(size) + { + if (this._shellVersion >= 42) { + return; + } + + this.panelCornerSetDefault(); + + if (size > 60 || size < 0) { + return; + } + + let classnameStarter = this._getAPIClassname('panel-corner'); + + this.UIStyleClassAdd(classnameStarter + size); + } + + /** + * set panel size to default + * + * @returns {void} + */ + panelSetDefaultSize() + { + if (!this._originals['panelHeight']) { + return; + } + + this.panelSetSize(this._originals['panelHeight'], false); + } + + /** + * change panel size + * + * @param {number} size 0 to 100 + * @param {boolean} fake true means it shouldn't change the last size, + * false otherwise + * + * @returns {void} + */ + panelSetSize(size, fake) + { + if (!this._originals['panelHeight']) { + this._originals['panelHeight'] = this._main.panel.height; + } + + if (size > 100 || size < 0) { + return; + } + + this._main.panel.height = size; + + if (!fake) { + this._panelSize = size; + } + + // to fix panel not getting out of place + this._emitPanelPositionChanged(); + } + + /** + * get the last size of the panel + * + * @returns {number} + */ + panelGetSize() + { + if (this._panelSize !== undefined) { + return this._panelSize; + } + + if (this._originals['panelHeight']) { + return this._originals['panelHeight']; + } + + return this._main.panel.height; + } + + /** + * emit refresh styles + * this is useful when changed style doesn't emit change because doesn't have + * standard styles. for example, style with only `-natural-hpadding` + * won't notify any change. so you need to call this function + * to refresh that + * + * @returns {void} + */ + _emitRefreshStyles() + { + let classname = this._getAPIClassname('refresh-styles'); + + this.UIStyleClassAdd(classname); + this.UIStyleClassRemove(classname); + } + + /** + * emit changed signal for panel position + * + * @param {boolean} calledFromChanger whether it is called from + * position changer. you should never call it with false from + * this.panelSetPosition() since it can cause recursion. + * + * @returns {void} + */ + _emitPanelPositionChanged(calledFromChanger = false) + { + if (this._timeoutIds['emitPanelPositionChanged']) { + this._glib.source_remove(this._timeoutIds['emitPanelPositionChanged']); + delete(this._timeoutIds['emitPanelPositionChanged']); + } + + if (this._timeoutIds['emitPanelPositionChanged2']) { + this._glib.source_remove(this._timeoutIds['emitPanelPositionChanged2']); + delete(this._timeoutIds['emitPanelPositionChanged2']); + } + + if (!calledFromChanger) { + this.panelSetPosition(this.panelGetPosition(), true); + } + + if (!this.isPanelVisible()) { + let mode = this._panelHideMode ? this._panelHideMode : 0; + this.panelHide(mode, 0); + } else { + // resize panel can fix windows going under panel + // we may not need it on X11, but it is needed on Wayland + // we also need delay after animation + // because without delay it many not fix the issue + let panelBox = this._main.layoutManager.panelBox; + let duration = this._addToAnimationDuration(180); + this._timeoutIds['emitPanelPositionChanged'] + = this._glib.timeout_add(this._glib.PRIORITY_IDLE, duration, () => { + delete(this._timeoutIds['emitPanelPositionChanged']); + this._main.panel.height++; + this._timeoutIds['emitPanelPositionChangedIn2'] + = this._glib.timeout_add(this._glib.PRIORITY_IDLE, 20, () => { + this._main.panel.height--; + delete(this._timeoutIds['emitPanelPositionChangedIn2']); + return this._glib.SOURCE_REMOVE; + }); + return this._glib.SOURCE_REMOVE; + }); + } + + this._fixLookingGlassPosition(); + } + + /** + * show panel + * + * @param {number} animationDuration in milliseconds. defaults to 150 + * + * @returns {void} + */ + panelShow(animationDuration = 150) + { + this._panelVisibility = true; + + let classname = this._getAPIClassname('no-panel'); + + if (!this.UIStyleClassContain(classname)) { + return; + } + + let overview = this._main.overview; + let searchEntryParent = overview.searchEntry.get_parent(); + let panelBox = this._main.layoutManager.panelBox; + + this._main.layoutManager.removeChrome(panelBox); + this._main.layoutManager.addChrome(panelBox, { + affectsStruts: true, + trackFullscreen: true, + }); + + panelBox.ease({ + translation_y: 0, + mode: this._clutter.AnimationMode.EASE, + duration: animationDuration, + onComplete: () => { + // hide and show can fix windows going under panel + panelBox.hide(); + panelBox.show(); + this._fixLookingGlassPosition(); + }, + }); + + if (this._overviewShowingSignal) { + overview.disconnect(this._overviewShowingSignal); + delete(this._overviewShowingSignal); + } + + if (this._overviewHidingSignal) { + overview.disconnect(this._overviewHidingSignal); + delete(this._overviewHidingSignal); + } + + if (this._hidePanelWorkareasChangedSignal) { + global.display.disconnect(this._hidePanelWorkareasChangedSignal); + delete(this._hidePanelWorkareasChangedSignal); + } + + searchEntryParent.set_style(`margin-top: 0;`); + + this.UIStyleClassRemove(classname); + } + + /** + * hide panel + * + * @param {mode} hide mode see PANEL_HIDE_MODE. defaults to hide all + * @param {boolean} force apply hide even if it is hidden + * @param {number} animationDuration in milliseconds. defaults to 150 + * + * @returns {void} + */ + panelHide(mode, animationDuration = 150) + { + this._panelVisibility = false; + this._panelHideMode = mode; + + let overview = this._main.overview; + let searchEntryParent = overview.searchEntry.get_parent(); + let panelBox = this._main.layoutManager.panelBox; + let panelHeight = this._main.panel.height; + let direction = (this.panelGetPosition() === PANEL_POSITION.BOTTOM) ? 1 : -1; + + this._main.layoutManager.removeChrome(panelBox); + this._main.layoutManager.addChrome(panelBox, { + affectsStruts: false, + trackFullscreen: true, + }); + + panelBox.ease({ + translation_y: panelHeight * direction, + mode: this._clutter.AnimationMode.EASE, + duration: animationDuration, + onComplete: () => { + // hide and show can fix windows going under panel + panelBox.hide(); + panelBox.show(); + this._fixLookingGlassPosition(); + }, + }); + + searchEntryParent.set_style(`margin-top: 0;`); + + if (this._overviewShowingSignal) { + overview.disconnect(this._overviewShowingSignal); + delete(this._overviewShowingSignal); + } + if (this._overviewHidingSignal) { + overview.disconnect(this._overviewHidingSignal); + delete(this._overviewHidingSignal); + } + + let appMenuOriginalVisibility; + + if (mode === PANEL_HIDE_MODE.DESKTOP) { + if (!this._overviewShowingSignal) { + this._overviewShowingSignal = overview.connect('showing', () => { + appMenuOriginalVisibility = this.isAppMenuVisible(); + this.appMenuHide(); + panelBox.ease({ + translation_y: 0, + mode: this._clutter.AnimationMode.EASE, + duration: 250, + }); + }); + } + if (!this._overviewHidingSignal) { + this._overviewHidingSignal = overview.connect('hiding', () => { + panelBox.ease({ + translation_y: panelHeight * direction, + mode: this._clutter.AnimationMode.EASE, + duration: 250, + onComplete: () => { + if (appMenuOriginalVisibility) { + this.appMenuShow(); + } else { + this.appMenuHide(); + } + }, + }); + }); + } + searchEntryParent.set_style(`margin-top: ${panelHeight}px;`); + } + + if (this._hidePanelWorkareasChangedSignal) { + global.display.disconnect(this._hidePanelWorkareasChangedSignal); + delete(this._hidePanelWorkareasChangedSignal); + } + + this._hidePanelWorkareasChangedSignal + = global.display.connect('workareas-changed', () => { + this.panelHide(this._panelHideMode, 0); + }); + + // when panel is hidden and search entry is visible, + // the search entry gets too close to the top, so we fix it with margin + // on GNOME 3 we need to have top and bottom margin for correct proportion + // but on GNOME 40 we don't need to keep proportion but give it more + // top margin to keep it less close to top + let classname = this._getAPIClassname('no-panel'); + this.UIStyleClassAdd(classname); + } + + /** + * check whether panel is visible + * + * @returns {boolean} + */ + isPanelVisible() + { + if (this._panelVisibility === undefined) { + return true; + } + + return this._panelVisibility; + } + + /** + * check whether dash is visible + * + * @returns {boolean} + */ + isDashVisible() + { + return this._dashVisibility === undefined || this._dashVisibility; + } + + /** + * show dash + * + * @returns {void} + */ + dashShow() + { + if (!this._main.overview.dash || this.isDashVisible()) { + return; + } + + this._dashVisibility = true; + + this._main.overview.dash.show(); + + if (this._shellVersion >= 40) { + this._main.overview.dash.height = -1; + this._main.overview.dash.setMaxSize(-1, -1); + } else { + this._main.overview.dash.width = -1; + this._main.overview.dash._maxHeight = -1; + } + + this._updateWindowPreviewOverlap(); + } + + /** + * hide dash + * + * @returns {void} + */ + dashHide() + { + if (!this._main.overview.dash || !this.isDashVisible()) { + return; + } + + this._dashVisibility = false; + + this._main.overview.dash.hide(); + + if (this._shellVersion >= 40) { + this._main.overview.dash.height = 0; + } else { + this._main.overview.dash.width = 0; + } + + this._updateWindowPreviewOverlap(); + } + + /** + * update window preview overlap + * + * @returns {void} + */ + _updateWindowPreviewOverlap() + { + if (this._shellVersion < 40) { + return; + } + + let wpp = this._windowPreview.WindowPreview.prototype; + + if (this.isDashVisible() && wpp.overlapHeightsOld) { + wpp.overlapHeights = wpp.overlapHeightsOld; + delete(wpp.overlapHeightsOld); + return; + } + + if (!this.isDashVisible()) { + wpp.overlapHeightsOld = wpp.overlapHeights; + wpp.overlapHeights = function () { + let [top, bottom] = this.overlapHeightsOld(); + return [top + 24, bottom + 24]; + }; + } + } + + /** + * enable gesture + * + * @returns {void} + */ + gestureEnable() + { + if (this._shellVersion >= 40) { + return; + } + + global.stage.get_actions().forEach(a => { + a.enabled = true; + }); + } + + /** + * disable gesture + * + * @returns {void} + */ + gestureDisable() + { + if (this._shellVersion >= 40) { + return; + } + + global.stage.get_actions().forEach(a => { + a.enabled = false; + }); + } + + /** + * add class name to the UI group + * + * @param {string} classname class name + * + * @returns {void} + */ + UIStyleClassAdd(classname) + { + this._main.layoutManager.uiGroup.add_style_class_name(classname); + } + + /** + * remove class name from UI group + * + * @param {string} classname class name + * + * @returns {void} + */ + UIStyleClassRemove(classname) + { + this._main.layoutManager.uiGroup.remove_style_class_name(classname); + } + + /** + * check whether UI group has class name + * + * @param {string} classname class name + * + * @returns {boolean} + */ + UIStyleClassContain(classname) + { + return this._main.layoutManager.uiGroup.has_style_class_name(classname); + } + + /** + * enable background menu + * + * @returns {void} + */ + backgroundMenuEnable() + { + if (!this._originals['backgroundMenu']) { + return; + } + + this._backgroundMenu.BackgroundMenu.prototype.open + = this._originals['backgroundMenu']; + } + + /** + * disable background menu + * + * @returns {void} + */ + backgroundMenuDisable() + { + if (!this._originals['backgroundMenu']) { + this._originals['backgroundMenu'] + = this._backgroundMenu.BackgroundMenu.prototype.open; + } + + this._backgroundMenu.BackgroundMenu.prototype.open = () => {}; + } + + /** + * show search + * + * @param {boolean} fake true means it just needs to do the job but + * don't need to change the search visibility status + * + * @returns {void} + */ + searchEntryShow(fake) + { + let classname = this._getAPIClassname('no-search'); + + if (!this.UIStyleClassContain(classname)) { + return; + } + + this.UIStyleClassRemove(classname); + + let searchEntry = this._main.overview.searchEntry; + let searchEntryParent = searchEntry.get_parent(); + + searchEntryParent.ease({ + height: searchEntry.height, + opacity: 255, + mode: this._clutter.AnimationMode.EASE, + duration: 110, + onComplete: () => { + searchEntryParent.height = -1; + searchEntry.ease({ + opacity: 255, + mode: this._clutter.AnimationMode.EASE, + duration: 700, + }); + }, + }); + + if (!fake) { + this._searchEntryVisibility = true; + } + } + + /** + * hide search + * + * @param {boolean} fake true means it just needs to do the job + * but don't need to change the search visibility status + * + * @returns {void} + */ + searchEntryHide(fake) + { + this.UIStyleClassAdd(this._getAPIClassname('no-search')); + + let searchEntry = this._main.overview.searchEntry; + let searchEntryParent = searchEntry.get_parent(); + + searchEntry.ease({ + opacity: 0, + mode: this._clutter.AnimationMode.EASE, + duration: 50, + }); + + searchEntryParent.ease({ + height: 0, + opacity: 0, + mode: this._clutter.AnimationMode.EASE, + duration: 120, + }); + + if (!fake) { + this._searchEntryVisibility = false; + } + } + + /** + * enable start search + * + * @returns {void} + */ + startSearchEnable() + { + this._startSearchSignal(true); + + if (!this._originals['startSearch']) { + return; + } + + let viewSelector + = this._main.overview.viewSelector || this._main.overview._overview.viewSelector; + + if (this._shellVersion >= 40 && this._searchController) { + this._searchController.SearchController.prototype.startSearch + = this._originals['startSearch']; + } else { + viewSelector.startSearch = this._originals['startSearch']; + } + } + + /** + * disable start search + * + * @returns {void} + */ + startSearchDisable() + { + this._startSearchSignal(false); + + let overview = this._main.overview; + let viewSelector = overview.viewSelector || overview.viewSelector; + + if (!this._originals['startSearch']) { + this._originals['startSearch'] + = (this._shellVersion >= 40 && this._searchController) + ? this._searchController.SearchController.prototype.startSearch + : viewSelector.startSearch; + } + + if (this._shellVersion >= 40 && this._searchController) { + this._searchController.SearchController.prototype.startSearch = () => {}; + } else { + viewSelector.startSearch = () => {}; + } + } + + /** + * add search signals that needs to be show search entry when the + * search entry is hidden + * + * @param {boolean} add true means add the signal, false means remove + * the signal + * + * @returns {void} + */ + _startSearchSignal(add) + { + let controller + = this._main.overview.viewSelector || + this._main.overview._overview.viewSelector || + this._main.overview._overview.controls._searchController; + + // remove + if (!add) { + if (this._searchActiveSignal) { + controller.disconnect(this._searchActiveSignal); + this._searchActiveSignal = null; + } + return; + } + + // add + if (this._searchActiveSignal) { + return; + } + + let bySearchController = this._shellVersion >= 40; + + let signalName = (bySearchController) ? 'notify::search-active' : 'page-changed'; + + this._searchActiveSignal = controller.connect(signalName, () => { + if (this._searchEntryVisibility) { + return; + } + + let inSearch + = (bySearchController) + ? controller.searchActive + : (controller.getActivePage() === this._viewSelector.ViewPage.SEARCH); + + if (inSearch) { + this.UIStyleClassAdd(this._getAPIClassname('type-to-search')); + this.searchEntryShow(true); + } else { + this.UIStyleClassRemove(this._getAPIClassname('type-to-search')); + this.searchEntryHide(true); + } + }); + } + + /** + * enable OSD + * + * @returns {void} + */ + OSDEnable() + { + if (!this._originals['osdWindowManagerShow']) { + return; + } + + this._main.osdWindowManager.show = this._originals['osdWindowManagerShow']; + } + + /** + * disable OSD + * + * @returns {void} + */ + OSDDisable() + { + if (!this._originals['osdWindowManagerShow']) { + this._originals['osdWindowManagerShow'] + = this._main.osdWindowManager.show; + } + + this._main.osdWindowManager.show = () => {}; + } + + /** + * enable workspace popup + * + * @returns {void} + */ + workspacePopupEnable() + { + if (this._shellVersion < 42) { + if (!this._originals['workspaceSwitcherPopupShow']) { + return; + } + this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype._show + = this._originals['workspaceSwitcherPopupShow']; + + return; + } + + if (!this._originals['workspaceSwitcherPopupDisplay']) { + return; + } + + this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display + = this._originals['workspaceSwitcherPopupDisplay'] + } + + /** + * disable workspace popup + * + * @returns {void} + */ + workspacePopupDisable() + { + if (this._shellVersion < 42) { + if (!this._originals['workspaceSwitcherPopupShow']) { + this._originals['workspaceSwitcherPopupShow'] + = this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype._show; + } + this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype._show = () => { + return false; + }; + + return; + } + + if (!this._originals['workspaceSwitcherPopupDisplay']) { + this._originals['workspaceSwitcherPopupDisplay'] + = this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display; + } + + this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display = (index) => { + return false; + }; + } + + /** + * show workspace switcher + * + * @returns {void} + */ + workspaceSwitcherShow() + { + if (this._shellVersion < 40) { + + if (!this._originals['getAlwaysZoomOut'] || + !this._originals['getNonExpandedWidth']) + { + return; + } + + let TSProto = this._overviewControls.ThumbnailsSlider.prototype; + + TSProto._getAlwaysZoomOut = this._originals['getAlwaysZoomOut']; + TSProto.getNonExpandedWidth = this._originals['getNonExpandedWidth']; + } + + // it should be before setting the switcher size + // because the size can be changed by removing the api class + this.UIStyleClassRemove(this._getAPIClassname('no-workspace')); + + if (this._workspaceSwitcherLastSize) { + this.workspaceSwitcherSetSize(this._workspaceSwitcherLastSize, false); + } else { + this.workspaceSwitcherSetDefaultSize(); + } + } + + /** + * hide workspace switcher + * + * @returns {void} + */ + workspaceSwitcherHide() + { + if (this._shellVersion < 40) { + + let TSProto = this._overviewControls.ThumbnailsSlider.prototype; + + if (!this._originals['getAlwaysZoomOut']) { + this._originals['getAlwaysZoomOut'] = TSProto._getAlwaysZoomOut; + } + + if (!this._originals['getNonExpandedWidth']) { + this._originals['getNonExpandedWidth'] = TSProto.getNonExpandedWidth; + } + + TSProto._getAlwaysZoomOut = () => { + return false; + }; + TSProto.getNonExpandedWidth = () => { + return 0; + }; + } + + this.workspaceSwitcherSetSize(0.0, true); + + // on GNOME 3.38 + // fix extra space that 3.38 leaves for no workspace with css + // on GNOME 40 + // we can hide the workspace only with css by scale=0 and + // no padding + this.UIStyleClassAdd(this._getAPIClassname('no-workspace')); + } + + /** + * check whether workspace switcher is visible + * + * @returns {boolean} + */ + isWorkspaceSwitcherVisible() + { + return !this.UIStyleClassContain(this._getAPIClassname('no-workspace')); + } + + /** + * get Secondary Monitor Display + * + * @returns {ui.WorkspacesView.SecondaryMonitorDisplay} + */ + _getSecondaryMonitorDisplay() + { + if (this._shellVersion < 40) { + return null; + } + + // for some reason the first time we get the value it returns null in 42 + // but it returns the correct value in second get + this._workspacesView.SecondaryMonitorDisplay; + + return this._workspacesView.SecondaryMonitorDisplay; + } + + /** + * set workspace switcher to its default size + * + * @returns {void} + */ + workspaceSwitcherSetDefaultSize() + { + if (this._shellVersion < 40) { + return; + } + + if (this._originals['MAX_THUMBNAIL_SCALE'] === undefined) { + return; + } + + let size = this._originals['MAX_THUMBNAIL_SCALE']; + + if (this.isWorkspaceSwitcherVisible()) { + this._workspaceThumbnail.MAX_THUMBNAIL_SCALE = size; + } + + if (this._originals['smd_getThumbnailsHeight'] !== undefined) { + let smd = this._getSecondaryMonitorDisplay(); + smd.prototype._getThumbnailsHeight = this._originals['smd_getThumbnailsHeight']; + } + + this._workspaceSwitcherLastSize = size; + } + + /** + * set workspace switcher size + * + * @param {number} size in float + * @param {boolean} fake true means don't change + * this._workspaceSwitcherLastSize, false otherwise + * + * @returns {void} + */ + workspaceSwitcherSetSize(size, fake) + { + if (this._shellVersion < 40) { + return; + } + + if (this._originals['MAX_THUMBNAIL_SCALE'] === undefined) { + this._originals['MAX_THUMBNAIL_SCALE'] + = this._workspaceThumbnail.MAX_THUMBNAIL_SCALE; + } + + if (this.isWorkspaceSwitcherVisible()) { + + this._workspaceThumbnail.MAX_THUMBNAIL_SCALE = size; + + // >> + // we are overriding the _getThumbnailsHeight() here with the same + // function as original but we change the MAX_THUMBNAIL_SCALE to our + // custom size. + // we do this because MAX_THUMBNAIL_SCALE is const and cannot be changed + let smd = this._getSecondaryMonitorDisplay(); + + if (this._originals['smd_getThumbnailsHeight'] === undefined) { + this._originals['smd_getThumbnailsHeight'] = smd.prototype._getThumbnailsHeight; + } + + smd.prototype._getThumbnailsHeight = function(box) { + if (!this._thumbnails.visible) + return 0; + + const [width, height] = box.get_size(); + const {expandFraction} = this._thumbnails; + const [thumbnailsHeight] = this._thumbnails.get_preferred_height(width); + + return Math.min( + thumbnailsHeight * expandFraction, + height * size); + } + // << + } + + if (!fake) { + this._workspaceSwitcherLastSize = size; + } + } + + /** + * add element to stage + * + * @param {St.Widget} element widget + * + * @returns {void} + */ + chromeAdd(element) + { + this._main.layoutManager.addChrome(element, { + affectsInputRegion : true, + affectsStruts : false, + trackFullscreen : true, + }); + } + + /** + * remove element from stage + * + * @param {St.Widget} element widget + * + * @returns {void} + */ + chromeRemove(element) + { + this._main.layoutManager.removeChrome(element); + } + + /** + * show activities button + * + * @returns {void} + */ + activitiesButtonShow() + { + if (!this.isLocked()) { + this._main.panel.statusArea['activities'].container.show(); + } + } + + /** + * hide activities button + * + * @returns {void} + */ + activitiesButtonHide() + { + this._main.panel.statusArea['activities'].container.hide(); + } + + /** + * show app menu + * + * @returns {void} + */ + appMenuShow() + { + if (!this.isLocked()) { + this._main.panel.statusArea['appMenu'].container.show(); + } + } + + /** + * hide app menu + * + * @returns {void} + */ + appMenuHide() + { + this._main.panel.statusArea['appMenu'].container.hide(); + } + + /** + * check whether app menu is visible + * + * @returns {boolean} + */ + isAppMenuVisible() + { + return this._main.panel.statusArea['appMenu'].container.visible; + } + + /** + * show date menu + * + * @returns {void} + */ + dateMenuShow() + { + if (!this.isLocked()) { + this._main.panel.statusArea['dateMenu'].container.show(); + } + } + + /** + * hide date menu + * + * @returns {void} + */ + dateMenuHide() + { + this._main.panel.statusArea['dateMenu'].container.hide(); + } + + /** + * show keyboard layout + * + * @returns {void} + */ + keyboardLayoutShow() + { + this._main.panel.statusArea['keyboard'].container.show(); + } + + /** + * hide keyboard layout + * + * @returns {void} + */ + keyboardLayoutHide() + { + this._main.panel.statusArea['keyboard'].container.hide(); + } + + /** + * show accessibility menu + * + * @returns {void} + */ + accessibilityMenuShow() + { + this._main.panel.statusArea['a11y'].container.show(); + } + + /** + * hide accessibility menu + * + * @returns {void} + */ + accessibilityMenuHide() + { + this._main.panel.statusArea['a11y'].container.hide(); + } + + /** + * show quick settings menu + * + * @returns {void} + */ + quickSettingsMenuShow() + { + if (this._shellVersion < 43) { + return; + } + + this._main.panel.statusArea['quickSettings'].container.show(); + } + + /** + * hide quick settings menu + * + * @returns {void} + */ + quickSettingsMenuHide() + { + if (this._shellVersion < 43) { + return; + } + + this._main.panel.statusArea['quickSettings'].container.hide(); + } + + /** + * show aggregate menu + * + * @returns {void} + */ + aggregateMenuShow() + { + if (this._shellVersion >= 43) { + return; + } + + this._main.panel.statusArea['aggregateMenu'].container.show(); + } + + /** + * hide aggregate menu + * + * @returns {void} + */ + aggregateMenuHide() + { + if (this._shellVersion >= 43) { + return; + } + + this._main.panel.statusArea['aggregateMenu'].container.hide(); + } + + /** + * set 'enableHotCorners' original value + * + * @returns {void} + */ + _setEnableHotCornersOriginal() + { + if (this._originals['enableHotCorners'] !== undefined) { + return; + } + + this._originals['enableHotCorners'] + = this._interfaceSettings.get_boolean('enable-hot-corners'); + } + + /** + * enable hot corners + * + * @returns {void} + */ + hotCornersEnable() + { + this._setEnableHotCornersOriginal(); + this._interfaceSettings.set_boolean('enable-hot-corners', true); + } + + /** + * disable hot corners + * + * @returns {void} + */ + hotCornersDisable() + { + this._setEnableHotCornersOriginal(); + this._interfaceSettings.set_boolean('enable-hot-corners', false); + } + + /** + * set the hot corners to default value + * + * @returns {void} + */ + hotCornersDefault() + { + this._setEnableHotCornersOriginal(); + + this._interfaceSettings.set_boolean('enable-hot-corners', + this._originals['enableHotCorners']); + } + + /** + * check whether lock dialog is currently showing + * + * @returns {boolean} + */ + isLocked() + { + return this._main.sessionMode.isLocked; + } + + /** + * enable window picker icon + * + * @returns {void} + */ + windowPickerIconEnable() + { + if (this._shellVersion < 40) { + return; + } + + this.UIStyleClassRemove(this._getAPIClassname('no-window-picker-icon')); + } + + /** + * disable window picker icon + * + * @returns {void} + */ + windowPickerIconDisable() + { + if (this._shellVersion < 40) { + return; + } + + this.UIStyleClassAdd(this._getAPIClassname('no-window-picker-icon')); + } + + /** + * show power icon + * + * @returns {void} + */ + powerIconShow() + { + this.UIStyleClassRemove(this._getAPIClassname('no-power-icon')); + } + + /** + * hide power icon + * + * @returns {void} + */ + powerIconHide() + { + this.UIStyleClassAdd(this._getAPIClassname('no-power-icon')); + } + + /** + * get primary monitor information + * + * @returns {false|Object} false when monitor does not exist | object + * x: int + * y: int + * width: int + * height: int + * geometryScale: float + */ + monitorGetInfo() + { + let pMonitor = this._main.layoutManager.primaryMonitor; + + if (!pMonitor) { + return false; + } + + return { + 'x': pMonitor.x, + 'y': pMonitor.y, + 'width': pMonitor.width, + 'height': pMonitor.height, + 'geometryScale': pMonitor.geometry_scale, + }; + } + + /** + * get panel position + * + * @returns {number} see PANEL_POSITION + */ + panelGetPosition() + { + if (this._panelPosition === undefined) { + return PANEL_POSITION.TOP; + } + + return this._panelPosition; + } + + /** + * move panel position + * + * @param {number} position see PANEL_POSITION + * @param {boolean} force allow to set even when the current position + * is the same + * + * @returns {void} + */ + panelSetPosition(position, force = false) + { + let monitorInfo = this.monitorGetInfo(); + let panelBox = this._main.layoutManager.panelBox; + + if (!force && position === this.panelGetPosition()) { + return; + } + + if (position === PANEL_POSITION.TOP) { + this._panelPosition = PANEL_POSITION.TOP; + if (this._workareasChangedSignal) { + global.display.disconnect(this._workareasChangedSignal); + this._workareasChangedSignal = null; + } + let topX = (monitorInfo) ? monitorInfo.x : 0; + let topY = (monitorInfo) ? monitorInfo.y : 0; + panelBox.set_position(topX, topY); + this.UIStyleClassRemove(this._getAPIClassname('bottom-panel')); + this._emitPanelPositionChanged(true); + return; + } + + this._panelPosition = PANEL_POSITION.BOTTOM; + + // only change it when a monitor detected + // 'workareas-changed' signal will do the job on next monitor detection + if (monitorInfo) { + let BottomX = monitorInfo.x; + let BottomY = monitorInfo.y + monitorInfo.height - this.panelGetSize(); + + panelBox.set_position(BottomX, BottomY); + this.UIStyleClassAdd(this._getAPIClassname('bottom-panel')); + } + + if (!this._workareasChangedSignal) { + this._workareasChangedSignal + = global.display.connect('workareas-changed', () => { + this.panelSetPosition(PANEL_POSITION.BOTTOM, true); + }); + } + + this._emitPanelPositionChanged(true); + } + + /** + * fix looking glass position + * + * @returns {void} + */ + _fixLookingGlassPosition() + { + let lookingGlassProto = this._lookingGlass.LookingGlass.prototype; + + if (this._originals['lookingGlassResize'] === undefined) { + this._originals['lookingGlassResize'] = lookingGlassProto._resize; + } + + if (this.panelGetPosition() === PANEL_POSITION.TOP && this.isPanelVisible()) { + + lookingGlassProto._resize = this._originals['lookingGlassResize']; + delete(lookingGlassProto._oldResize); + delete(this._originals['lookingGlassResize']); + if (this._main.lookingGlass) { + this._main.lookingGlass._resize(); + } + + return; + } + + if (lookingGlassProto._oldResize === undefined) { + lookingGlassProto._oldResize = this._originals['lookingGlassResize']; + + const Main = this._main; + + lookingGlassProto._resize = function () { + let panelHeight = Main.layoutManager.panelBox.height; + this._oldResize(); + this._targetY -= panelHeight; + this._hiddenY -= panelHeight; + }; + } + } + + /** + * enable panel arrow + * + * @returns {void} + */ + panelArrowEnable() + { + if (this._shellVersion >= 40) { + return; + } + + this.UIStyleClassRemove(this._getAPIClassname('no-panel-arrow')); + } + + /** + * disable panel arrow + * + * @returns {void} + */ + panelArrowDisable() + { + if (this._shellVersion >= 40) { + return; + } + + this.UIStyleClassAdd(this._getAPIClassname('no-panel-arrow')); + } + + /** + * enable panel notification icon + * + * @returns {void} + */ + panelNotificationIconEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-panel-notification-icon')); + } + + /** + * disable panel notification icon + * + * @returns {void} + */ + panelNotificationIconDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-panel-notification-icon')); + } + + /** + * disable app menu icon + * + * @returns {void} + */ + appMenuIconEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-app-menu-icon')); + } + + /** + * disable app menu icon + * + * @returns {void} + */ + appMenuIconDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-app-menu-icon')); + } + + /** + * disable app menu label + * + * @returns {void} + */ + appMenuLabelEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-app-menu-label')); + } + + /** + * disable app menu label + * + * @returns {void} + */ + appMenuLabelDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-app-menu-label')); + } + + /** + * set the clock menu position + * + * @param {number} pos see PANEL_BOX_POSITION + * @param {number} offset starts from 0 + * + * @returns {void} + */ + clockMenuPositionSet(pos, offset) + { + let dateMenu = this._main.panel.statusArea['dateMenu']; + + let panelBoxs = [ + this._main.panel._centerBox, + this._main.panel._rightBox, + this._main.panel._leftBox, + ]; + + let fromPos = -1; + let fromIndex = -1; + let toIndex = -1; + let childLength = 0; + for (let i = 0; i <= 2; i++) { + let child = panelBoxs[i].get_children(); + let childIndex = child.indexOf(dateMenu.container); + if (childIndex !== -1) { + fromPos = i; + fromIndex = childIndex; + childLength = panelBoxs[pos].get_children().length; + toIndex = (offset > childLength) ? childLength : offset; + break; + } + } + + // couldn't find the from and to position because it has been removed + if (fromPos === -1 || fromIndex === -1 || toIndex === -1) { + return; + } + + if (pos === fromPos && toIndex === fromIndex) { + return; + } + + panelBoxs[fromPos].remove_actor(dateMenu.container); + panelBoxs[pos].insert_child_at_index(dateMenu.container, toIndex); + + if (this.isLocked()) { + this.dateMenuHide(); + } + } + + /** + * enable show apps button + * + * @returns {void} + */ + showAppsButtonEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-show-apps-button')); + } + + /** + * disable show apps button + * + * @returns {void} + */ + showAppsButtonDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-show-apps-button')); + } + + /** + * set animation speed as default + * + * @returns {void} + */ + animationSpeedSetDefault() + { + if (this._originals['StSlowDownFactor'] === undefined) { + return; + } + + this._st.Settings.get().slow_down_factor = this._originals['StSlowDownFactor']; + } + + /** + * change animation speed + * + * @param {number} factor in float. bigger number means slower + * + * @returns {void} + */ + animationSpeedSet(factor) + { + if (this._originals['StSlowDownFactor'] === undefined) { + this._originals['StSlowDownFactor'] + = this._st.Settings.get().slow_down_factor; + } + + this._st.Settings.get().slow_down_factor = factor; + } + + /** + * set the enable animation as default + * + * @returns {void} + */ + enableAnimationsSetDefault() + { + if (this._originals['enableAnimations'] === undefined) { + return; + } + + let status = this._originals['enableAnimations']; + + this._interfaceSettings.set_boolean('enable-animations', status); + } + + /** + * set the enable animation status + * + * @param {boolean} status true to enable, false otherwise + * + * @returns {void} + */ + enableAnimationsSet(status) + { + if (this._originals['enableAnimations'] === undefined) { + this._originals['enableAnimations'] + = this._interfaceSettings.get_boolean('enable-animations'); + } + + this._interfaceSettings.set_boolean('enable-animations', status); + } + + /** + * add icon to the activities button + * + * @param {number} type see ICON_TYPE + * @param {string} icon file URI or icon name + * @param {boolean} monochrome to show icon in monochrome + * @param {boolean} holdLabel whether label should be available + * + * @returns {void} + */ + activitiesButtonAddIcon(type, icon, monochrome, holdLabel) + { + let iconSize = this.panelIconGetSize() - this._panel.APP_MENU_ICON_MARGIN; + let activities = this._main.panel.statusArea['activities']; + + this.activitiesButtonRemoveIcon(); + + if (!this._activitiesBtn) { + this._activitiesBtn = {}; + } + + let iconClassname + = (monochrome) + ? this._getAPIClassname('activities-button-icon-monochrome') + : this._getAPIClassname('activities-button-icon'); + + this._activitiesBtn.icon = new this._st.Icon({ + icon_size: iconSize, + style_class: iconClassname, + y_align: this._clutter.ActorAlign.CENTER, + }); + + if (monochrome) { + let effect = new this._clutter.DesaturateEffect(); + this._activitiesBtn.icon.add_effect(effect); + + this._activitiesBtn.icon.connect('style-changed', () => { + let themeNode = this._activitiesBtn.icon.get_theme_node(); + effect.enabled + = themeNode.get_icon_style() == this._st.IconStyle.SYMBOLIC; + }); + } + + switch (type) { + + case ICON_TYPE.NAME: + if (!icon) { + return; + } + this._activitiesBtn.icon.set_icon_name(icon); + break; + + case ICON_TYPE.URI: + let file = this._gio.File.new_for_uri(icon); + let filePathExists = file.query_exists(null); + if (!filePathExists) { + return; + } + let gicon = this._gio.icon_new_for_string(file.get_path()); + this._activitiesBtn.icon.set_gicon(gicon); + break; + + default: + return; + } + + activities.remove_actor(activities.label_actor); + + // add as icon + if (!holdLabel) { + this.UIStyleClassAdd(this._getAPIClassname('activities-button-no-label')); + activities.add_actor(this._activitiesBtn.icon); + return; + } + + // add as container (icon and text) + this._activitiesBtn.container = new this._st.BoxLayout(); + this._activitiesBtn.container.add_actor(this._activitiesBtn.icon); + this._activitiesBtn.container.add_actor(activities.label_actor); + + activities.add_actor(this._activitiesBtn.container); + } + + /** + * remove icon from activities button if it has been added before + * + * @returns {void} + */ + activitiesButtonRemoveIcon() + { + let activities = this._main.panel.statusArea['activities']; + + if (!this._activitiesBtn) { + return; + } + + if (this._activitiesBtn.container) { + this._activitiesBtn.container.remove_actor(this._activitiesBtn.icon); + this._activitiesBtn.container.remove_actor(activities.label_actor); + activities.remove_actor(this._activitiesBtn.container); + this._activitiesBtn.icon = null; + this._activitiesBtn.container = null; + } + + if (this._activitiesBtn.icon && activities.contains(this._activitiesBtn.icon)) { + activities.remove_actor(this._activitiesBtn.icon); + this._activitiesBtn.icon = null; + } + + if (!activities.contains(activities.label_actor)) { + activities.add_actor(activities.label_actor); + } + + this.UIStyleClassRemove(this._getAPIClassname('activities-button-no-label')); + } + + /** + * set activities button icon size + * + * @param {number} size 1-60 + * + * @returns {void} + */ + _activitiesButtonIconSetSize(size) + { + if (size < 1 || size > 60) { + return; + } + + let activities = this._main.panel.statusArea['activities']; + + if (!this._activitiesBtn || !this._activitiesBtn.icon) { + return; + } + + this._activitiesBtn.icon.icon_size = size - this._panel.APP_MENU_ICON_MARGIN; + } + + /** + * enable focus when window demands attention happens + * + * @returns {void} + */ + windowDemandsAttentionFocusEnable() + { + if (this._displayWindowDemandsAttentionSignal) { + return; + } + + let display = global.display; + + this._displayWindowDemandsAttentionSignal + = display.connect('window-demands-attention', (display, window) => { + if (!window || window.has_focus() || window.is_skip_taskbar()) { + return; + } + this._main.activateWindow(window); + }); + + // since removing '_windowDemandsAttentionId' doesn't have any effect + // we remove the original signal and re-connect it on disable + let signalId + = (this._shellVersion < 42) + ? this._main.windowAttentionHandler._windowDemandsAttentionId + : this._getSignalId(global.display, 'window-demands-attention'); + + display.disconnect(signalId); + } + + /** + * disable focus when window demands attention happens + * + * @returns {void} + */ + windowDemandsAttentionFocusDisable() + { + if (!this._displayWindowDemandsAttentionSignal) { + return; + } + + let display = global.display; + + display.disconnect(this._displayWindowDemandsAttentionSignal); + this._displayWindowDemandsAttentionSignal = null; + + let wah = this._main.windowAttentionHandler; + wah._windowDemandsAttentionId = display.connect('window-demands-attention', + wah._onWindowDemandsAttention.bind(wah)); + } + + /** + * set startup status + * + * @param {number} status see SHELL_STATUS for available status + * + * @returns {void} + */ + startupStatusSet(status) + { + if (this._shellVersion < 40) { + return; + } + + if (!this._main.layoutManager._startingUp) { + return; + } + + if (this._originals['sessionModeHasOverview'] === undefined) { + this._originals['sessionModeHasOverview'] + = this._main.sessionMode.hasOverview; + } + + let ControlsState = this._overviewControls.ControlsState; + let Controls = this._main.overview._overview.controls; + + switch (status) { + + case SHELL_STATUS.NONE: + this._main.sessionMode.hasOverview = false; + this._main.layoutManager.startInOverview = false; + Controls._stateAdjustment.value = ControlsState.HIDDEN; + break; + + case SHELL_STATUS.OVERVIEW: + this._main.sessionMode.hasOverview = true; + this._main.layoutManager.startInOverview = true; + break; + } + + if (!this._startupCompleteSignal) { + this._startupCompleteSignal + = this._main.layoutManager.connect('startup-complete', () => { + this._main.sessionMode.hasOverview + = this._originals['sessionModeHasOverview']; + }); + } + } + + /** + * set startup status to default + * + * @returns {void} + */ + startupStatusSetDefault() + { + if (this._originals['sessionModeHasOverview'] === undefined) { + return; + } + + if (this._startupCompleteSignal) { + this._main.layoutManager.disconnect(this._startupCompleteSignal); + } + } + + /** + * set dash icon size to default + * + * @returns {void} + */ + dashIconSizeSetDefault() + { + let classnameStarter = this._getAPIClassname('dash-icon-size'); + + DASH_ICON_SIZES.forEach(size => { + this.UIStyleClassRemove(classnameStarter + size); + }); + } + + /** + * set dash icon size + * + * @param {number} size in pixels + * see DASH_ICON_SIZES for available sizes + * + * @returns {void} + */ + dashIconSizeSet(size) + { + this.dashIconSizeSetDefault(); + + if (!DASH_ICON_SIZES.includes(size)) { + return; + } + + let classnameStarter = this._getAPIClassname('dash-icon-size'); + + this.UIStyleClassAdd(classnameStarter + size); + } + + /** + * disable workspaces in app grid + * + * @returns {void} + */ + workspacesInAppGridDisable() + { + if (this._shellVersion < 40) { + return; + } + + if (!this._originals['computeWorkspacesBoxForState']) { + let ControlsManagerLayout = this._overviewControls.ControlsManagerLayout; + this._originals['computeWorkspacesBoxForState'] + = ControlsManagerLayout.prototype._computeWorkspacesBoxForState; + } + + let controlsLayout = this._main.overview._overview._controls.layout_manager; + + controlsLayout._computeWorkspacesBoxForState = (state, ...args) => { + + let box = this._originals['computeWorkspacesBoxForState'].call( + controlsLayout, state, ...args); + + if (state === this._overviewControls.ControlsState.APP_GRID) { + box.set_size(box.get_width(), 0); + } + + return box; + }; + } + + /** + * enable workspaces in app grid + * + * @returns {void} + */ + workspacesInAppGridEnable() + { + if (!this._originals['computeWorkspacesBoxForState']) { + return; + } + + let controlsLayout = this._main.overview._overview._controls.layout_manager; + + controlsLayout._computeWorkspacesBoxForState + = this._originals['computeWorkspacesBoxForState']; + } + + /** + * change notification banner position + * + * @param {number} pos + * see XY_POSITION for available positions + * + * @returns {void} + */ + notificationBannerPositionSet(pos) + { + let messageTray = this._main.messageTray; + let bannerBin = messageTray._bannerBin; + + if (this._originals['bannerAlignmentX'] === undefined) { + this._originals['bannerAlignmentX'] = messageTray.bannerAlignment; + } + + if (this._originals['bannerAlignmentY'] === undefined) { + this._originals['bannerAlignmentY'] = bannerBin.get_y_align(); + } + + if (this._originals['hideNotification'] === undefined) { + this._originals['hideNotification'] = messageTray._hideNotification; + } + + // TOP + messageTray._hideNotification = this._originals['hideNotification']; + + bannerBin.set_y_align(this._clutter.ActorAlign.START); + + if (pos === XY_POSITION.TOP_START) { + messageTray.bannerAlignment = this._clutter.ActorAlign.START; + return; + } + + if (pos === XY_POSITION.TOP_END) { + messageTray.bannerAlignment = this._clutter.ActorAlign.END; + return; + } + + if (pos === XY_POSITION.TOP_CENTER) { + messageTray.bannerAlignment = this._clutter.ActorAlign.CENTER; + return; + } + + // BOTTOM + + // >> + // This block is going to fix the animation when the notification is + // in bottom area + // this is the same function from (ui.messageTray.messageTray._hideNotification) + // with clutter animation mode set to EASE. + // because the EASE_OUT_BACK (original code) causes glitch when + // the tray is on bottom + const State = this._messageTray.State; + const ANIMATION_TIME = this._messageTray.ANIMATION_TIME; + const Clutter = this._clutter; + const SHELL_VERSION = this._shellVersion; + + messageTray._hideNotification = function (animate) { + this._notificationFocusGrabber.ungrabFocus(); + + if (SHELL_VERSION >= 42) { + this._banner.disconnectObject(this); + } else { + if (this._bannerClickedId) { + this._banner.disconnect(this._bannerClickedId); + this._bannerClickedId = 0; + } + if (this._bannerUnfocusedId) { + this._banner.disconnect(this._bannerUnfocusedId); + this._bannerUnfocusedId = 0; + } + } + + this._resetNotificationLeftTimeout(); + this._bannerBin.remove_all_transitions(); + + if (animate) { + this._notificationState = State.HIDING; + this._bannerBin.ease({ + opacity: 0, + duration: ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE, + }); + this._bannerBin.ease({ + opacity: 0, + y: this._bannerBin.height, + duration: ANIMATION_TIME, + mode: Clutter.AnimationMode.EASE, + onComplete: () => { + this._notificationState = State.HIDDEN; + this._hideNotificationCompleted(); + this._updateState(); + }, + }); + } else { + this._bannerBin.y = this._bannerBin.height; + this._bannerBin.opacity = 0; + this._notificationState = State.HIDDEN; + this._hideNotificationCompleted(); + } + } + // << + + bannerBin.set_y_align(this._clutter.ActorAlign.END); + + if (pos === XY_POSITION.BOTTOM_START) { + messageTray.bannerAlignment = this._clutter.ActorAlign.START; + return; + } + + if (pos === XY_POSITION.BOTTOM_END) { + messageTray.bannerAlignment = this._clutter.ActorAlign.END; + return; + } + + if (pos === XY_POSITION.BOTTOM_CENTER) { + messageTray.bannerAlignment = this._clutter.ActorAlign.CENTER; + return; + } + } + + /** + * set notification banner position to default position + * + * @returns {void} + */ + notificationBannerPositionSetDefault() + { + if (this._originals['bannerAlignmentX'] === undefined || + this._originals['bannerAlignmentY'] === undefined || + this._originals['hideNotification'] === undefined + ) { + return; + } + + let messageTray = this._main.messageTray; + let bannerBin = messageTray._bannerBin; + + messageTray.bannerAlignment = this._originals['bannerAlignmentX']; + bannerBin.set_y_align(this._originals['bannerAlignmentY']); + messageTray._hideNotification = this._originals['hideNotification']; + } + + /** + * set the workspace switcher to always/never show + * + * @param {boolean} show true for always show, false for never show + * + * @returns {void} + */ + workspaceSwitcherShouldShow(shouldShow = true) + { + if (this._shellVersion < 40) { + return; + } + + let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; + + if (!this._originals['updateShouldShow']) { + this._originals['updateShouldShow'] = ThumbnailsBoxProto._updateShouldShow; + } + + ThumbnailsBoxProto._updateShouldShow = function () { + if (this._shouldShow === shouldShow) { + return; + } + this._shouldShow = shouldShow; + this.notify('should-show'); + }; + } + + /** + * set the always show workspace switcher status to default + * + * @returns {void} + */ + workspaceSwitcherShouldShowSetDefault() + { + if (!this._originals['updateShouldShow']) { + return; + } + + let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; + ThumbnailsBoxProto._updateShouldShow = this._originals['updateShouldShow']; + } + + /** + * set panel button hpadding to default + * + * @returns {void} + */ + panelButtonHpaddingSetDefault() + { + if (this._panelButtonHpaddingSize === undefined) { + return; + } + + let classnameStarter = this._getAPIClassname('panel-button-padding-size'); + this.UIStyleClassRemove(classnameStarter + this._panelButtonHpaddingSize); + this._emitRefreshStyles(); + + delete this._panelButtonHpaddingSize; + } + + /** + * set panel button hpadding size + * + * @param {number} size in pixels (0 - 60) + * + * @returns {void} + */ + panelButtonHpaddingSizeSet(size) + { + this.panelButtonHpaddingSetDefault(); + + if (size < 0 || size > 60) { + return; + } + + this._panelButtonHpaddingSize = size; + + let classnameStarter = this._getAPIClassname('panel-button-padding-size'); + this.UIStyleClassAdd(classnameStarter + size); + this._emitRefreshStyles(); + } + + /** + * set panel indicator padding to default + * + * @returns {void} + */ + panelIndicatorPaddingSetDefault() + { + if (this._panelIndicatorPaddingSize === undefined) { + return; + } + + let classnameStarter = this._getAPIClassname('panel-indicator-padding-size'); + this.UIStyleClassRemove(classnameStarter + this._panelIndicatorPaddingSize); + this._emitRefreshStyles(); + + delete this._panelIndicatorPaddingSize; + } + + /** + * set panel indicator padding size + * + * @param {number} size in pixels (0 - 60) + * + * @returns {void} + */ + panelIndicatorPaddingSizeSet(size) + { + this.panelIndicatorPaddingSetDefault(); + + if (size < 0 || size > 60) { + return; + } + + this._panelIndicatorPaddingSize = size; + + let classnameStarter = this._getAPIClassname('panel-indicator-padding-size'); + this.UIStyleClassAdd(classnameStarter + size); + this._emitRefreshStyles(); + } + + /** + * get window preview prototype + * + * @returns {Object} + */ + _windowPreviewGetPrototype() + { + if (this._shellVersion <= 3.36) { + return this._workspace.WindowOverlay.prototype; + } + + return this._windowPreview.WindowPreview.prototype; + } + + /** + * enable window preview caption + * + * @returns {void} + */ + windowPreviewCaptionEnable() + { + if (!this._originals['windowPreviewGetCaption']) { + return; + } + + let windowPreviewProto = this._windowPreviewGetPrototype(); + windowPreviewProto._getCaption = this._originals['windowPreviewGetCaption']; + + this.UIStyleClassRemove(this._getAPIClassname('no-window-caption')); + } + + /** + * disable window preview caption + * + * @returns {void} + */ + windowPreviewCaptionDisable() + { + let windowPreviewProto = this._windowPreviewGetPrototype(); + + if (!this._originals['windowPreviewGetCaption']) { + this._originals['windowPreviewGetCaption'] = windowPreviewProto._getCaption; + } + + windowPreviewProto._getCaption = () => { + return ''; + }; + + this.UIStyleClassAdd(this._getAPIClassname('no-window-caption')); + } + + /** + * set workspace background border radius to default size + * + * @returns {void} + */ + workspaceBackgroundRadiusSetDefault() + { + if (this._workspaceBackgroundRadiusSize === undefined) { + return; + } + + let workspaceBackgroundProto = this._workspace.WorkspaceBackground.prototype; + + workspaceBackgroundProto._updateBorderRadius + = this._originals['workspaceBackgroundUpdateBorderRadius']; + + let classnameStarter = this._getAPIClassname('workspace-background-radius-size'); + this.UIStyleClassRemove(classnameStarter + this._workspaceBackgroundRadiusSize); + + delete this._workspaceBackgroundRadiusSize; + } + + /** + * set workspace background border radius size + * + * @param {number} size in pixels (0 - 60) + * + * @returns {void} + */ + workspaceBackgroundRadiusSet(size) + { + if (this._shellVersion < 40) { + return; + } + + if (size < 0 || size > 60) { + return; + } + + this.workspaceBackgroundRadiusSetDefault(); + + let workspaceBackgroundProto = this._workspace.WorkspaceBackground.prototype; + + if (!this._originals['workspaceBackgroundUpdateBorderRadius']) { + this._originals['workspaceBackgroundUpdateBorderRadius'] + = workspaceBackgroundProto._updateBorderRadius; + } + + const Util = this._util; + const St = this._st; + + workspaceBackgroundProto._updateBorderRadius = function () { + const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); + const cornerRadius = scaleFactor * size; + + const backgroundContent = this._bgManager.backgroundActor.content; + backgroundContent.rounded_clip_radius = + Util.lerp(0, cornerRadius, this._stateAdjustment.value); + } + + this._workspaceBackgroundRadiusSize = size; + + let classnameStarter = this._getAPIClassname('workspace-background-radius-size'); + this.UIStyleClassAdd(classnameStarter + size); + } + + /** + * enable workspace wraparound + * + * @returns {void} + */ + workspaceWraparoundEnable() + { + let metaWorkspaceProto = this._meta.Workspace.prototype; + + if (!this._originals['metaWorkspaceGetNeighbor']) { + this._originals['metaWorkspaceGetNeighbor'] + = metaWorkspaceProto.get_neighbor; + } + + const Meta = this._meta; + + metaWorkspaceProto.get_neighbor = function (dir) { + + let index = this.index(); + let lastIndex = global.workspace_manager.n_workspaces - 1; + let neighborIndex; + + if (dir === Meta.MotionDirection.UP || dir === Meta.MotionDirection.LEFT) { + // prev + neighborIndex = (index > 0) ? index - 1 : lastIndex; + } else { + // next + neighborIndex = (index < lastIndex) ? index + 1 : 0; + } + + return global.workspace_manager.get_workspace_by_index(neighborIndex); + }; + } + + /** + * disable workspace wraparound + * + * @returns {void} + */ + workspaceWraparoundDisable() + { + if (!this._originals['metaWorkspaceGetNeighbor']) { + return; + } + + let metaWorkspaceProto = this._meta.Workspace.prototype; + metaWorkspaceProto.get_neighbor = this._originals['metaWorkspaceGetNeighbor']; + } + + /** + * enable window preview close button + * + * @returns {void} + */ + windowPreviewCloseButtonEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-window-close')); + } + + /** + * disable window preview close button + * + * @returns {void} + */ + windowPreviewCloseButtonDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-window-close')); + } + + /** + * enable ripple box + * + * @returns {void} + */ + rippleBoxEnable() + { + this.UIStyleClassRemove(this._getAPIClassname('no-ripple-box')); + } + + /** + * disable ripple box + * + * @returns {void} + */ + rippleBoxDisable() + { + this.UIStyleClassAdd(this._getAPIClassname('no-ripple-box')); + } + + /** + * enable double super press to toggle app grid + * + * @returns {void} + */ + doubleSuperToAppGridEnable() + { + if (this._shellVersion < 40 || this._isDoubleSuperToAppGrid === true) { + return; + } + + if (!this._overlayKeyNewSignalId) { + return; + } + + global.display.disconnect(this._overlayKeyNewSignalId); + + this._gobject.signal_handler_unblock( + global.display, + this._overlayKeyOldSignalId + ); + + delete(this._overlayKeyNewSignalId); + delete(this._overlayKeyOldSignalId); + + this._isDoubleSuperToAppGrid = true; + } + + /** + * disable double super press to toggle app grid + * + * @returns {void} + */ + doubleSuperToAppGridDisable() + { + if (this._shellVersion < 40 || this._isDoubleSuperToAppGrid === false) { + return; + } + + this._overlayKeyOldSignalId = this._getSignalId(global.display, 'overlay-key'); + + if (!this._overlayKeyOldSignalId) { + return; + } + + this._gobject.signal_handler_block(global.display, this._overlayKeyOldSignalId); + + this._overlayKeyNewSignalId = global.display.connect('overlay-key', () => { + this._main.overview.toggle(); + }); + + this._isDoubleSuperToAppGrid = false; + } + + /** + * set default OSD position + * + * @returns {void} + */ + osdPositionSetDefault() + { + if (this._shellVersion < 42) { + return; + } + + if (!this._originals['osdWindowShow']) { + return; + } + + let osdWindowProto = this._osdWindow.OsdWindow.prototype; + + osdWindowProto.show = this._originals['osdWindowShow']; + + delete(osdWindowProto._oldShow); + delete(this._originals['osdWindowShow']); + + if ( + this._originals['osdWindowXAlign'] !== undefined && + this._originals['osdWindowYAlign'] !== undefined + ) { + let osdWindows = this._main.osdWindowManager._osdWindows; + osdWindows.forEach(osdWindow => { + osdWindow.x_align = this._originals['osdWindowXAlign']; + osdWindow.y_align = this._originals['osdWindowYAlign']; + }); + delete(this._originals['osdWindowXAlign']); + delete(this._originals['osdWindowYAlign']); + } + + this.UIStyleClassRemove(this._getAPIClassname('osd-position-top')); + this.UIStyleClassRemove(this._getAPIClassname('osd-position-bottom')); + this.UIStyleClassRemove(this._getAPIClassname('osd-position-center')); + } + + /** + * set OSD position + * + * @param int pos position XY_POSITION + * + * @returns {void} + */ + osdPositionSet(pos) + { + if (this._shellVersion < 42) { + return; + } + + let osdWindowProto = this._osdWindow.OsdWindow.prototype; + + if (!this._originals['osdWindowShow']) { + this._originals['osdWindowShow'] = osdWindowProto.show; + } + + if ( + this._originals['osdWindowXAlign'] === undefined || + this._originals['osdWindowYAlign'] === undefined + ) { + let osdWindows = this._main.osdWindowManager._osdWindows; + this._originals['osdWindowXAlign'] = osdWindows[0].x_align; + this._originals['osdWindowYAlign'] = osdWindows[0].y_align; + } + + if (osdWindowProto._oldShow === undefined) { + osdWindowProto._oldShow = this._originals['osdWindowShow']; + } + + let [xAlign, yAlign] = this._xyAlignGet(pos); + osdWindowProto.show = function () { + this.x_align = xAlign; + this.y_align = yAlign; + this._oldShow(); + }; + + if ( + pos === XY_POSITION.TOP_START || + pos === XY_POSITION.TOP_CENTER || + pos === XY_POSITION.TOP_END + ) { + this.UIStyleClassAdd(this._getAPIClassname('osd-position-top')); + } + + if ( + pos === XY_POSITION.BOTTOM_START || + pos === XY_POSITION.BOTTOM_CENTER || + pos === XY_POSITION.BOTTOM_END + ) { + this.UIStyleClassAdd(this._getAPIClassname('osd-position-bottom')); + } + + if ( + pos === XY_POSITION.CENTER_START || + pos === XY_POSITION.CENTER_CENTER || + pos === XY_POSITION.CENTER_END + ) { + this.UIStyleClassAdd(this._getAPIClassname('osd-position-center')); + } + } + + /** + * show weather in date menu + * + * @returns {void} + */ + weatherShow() + { + this.UIStyleClassRemove(this._getAPIClassname('no-weather')); + } + + /** + * hide weather in date menu + * + * @returns {void} + */ + weatherHide() + { + this.UIStyleClassAdd(this._getAPIClassname('no-weather')); + } + + /** + * show world clocks in date menu + * + * @returns {void} + */ + worldClocksShow() + { + this.UIStyleClassRemove(this._getAPIClassname('no-world-clocks')); + } + + /** + * hide world clocks in date menu + * + * @returns {void} + */ + worldClocksHide() + { + this.UIStyleClassAdd(this._getAPIClassname('no-world-clocks')); + } + + /** + * show events button in date menu + * + * @returns {void} + */ + eventsButtonShow() + { + this.UIStyleClassRemove(this._getAPIClassname('no-events-button')); + } + + /** + * hide events button in date menu + * + * @returns {void} + */ + eventsButtonHide() + { + this.UIStyleClassAdd(this._getAPIClassname('no-events-button')); + } + + /** + * show calendar in date menu + * + * @returns {void} + */ + calendarShow() + { + this._main.panel.statusArea.dateMenu._calendar.show(); + } + + /** + * hide calendar in date menu + * + * @returns {void} + */ + calendarHide() + { + this._main.panel.statusArea.dateMenu._calendar.hide(); + } + + /** + * set default panel icon size + * + * @returns {void} + */ + panelIconSetDefaultSize() + { + if (this._panelIconSize === undefined || !this._originals['panelIconSize']) { + return; + } + + let classnameStarter = this._getAPIClassname('panel-icon-size'); + this.UIStyleClassRemove(classnameStarter + this._panelIconSize); + this._emitRefreshStyles(); + + let defaultSize = this._originals['panelIconSize']; + this._panel.PANEL_ICON_SIZE = defaultSize; + this._main.panel.statusArea['dateMenu']._indicator.set_icon_size(defaultSize); + this._main.panel.statusArea['appMenu']._onIconThemeChanged(); + this._activitiesButtonIconSetSize(defaultSize); + + delete(this._panelIconSize); + } + + /** + * set panel icon size + * + * @param {number} size 1-60 + * + * @returns {void} + */ + panelIconSetSize(size) + { + if (size < 1 || size > 60) { + return; + } + + if (!this._originals['panelIconSize']) { + this._originals['panelIconSize'] = this._panel.PANEL_ICON_SIZE; + } + + let classnameStarter = this._getAPIClassname('panel-icon-size'); + this.UIStyleClassRemove(classnameStarter + this.panelIconGetSize()); + this.UIStyleClassAdd(classnameStarter + size); + this._emitRefreshStyles(); + + this._panel.PANEL_ICON_SIZE = size; + this._main.panel.statusArea['dateMenu']._indicator.set_icon_size(size); + this._main.panel.statusArea['appMenu']._onIconThemeChanged(); + this._activitiesButtonIconSetSize(size); + + this._panelIconSize = size; + } + + /** + * get panel icon size + * + * @returns {void} + */ + panelIconGetSize() + { + if (this._panelIconSize !== undefined) { + return this._panelIconSize; + } + + return this._panel.PANEL_ICON_SIZE; + } + + /** + * show dash separator + * + * @returns {void} + */ + dashSeparatorShow() + { + if (this._shellVersion < 40) { + return; + } + + this.UIStyleClassRemove(this._getAPIClassname('no-dash-separator')); + } + + /** + * hide dash separator + * + * @returns {void} + */ + dashSeparatorHide() + { + if (this._shellVersion < 40) { + return; + } + + this.UIStyleClassAdd(this._getAPIClassname('no-dash-separator')); + } + + /** + * get looking glass size + * + * @returns {array} + * width: int + * height: int + */ + _lookingGlassGetSize() + { + let lookingGlass = this._main.createLookingGlass(); + + return [lookingGlass.width, lookingGlass.height]; + } + + /** + * set default looking glass size + * + * @returns {void} + */ + lookingGlassSetDefaultSize() + { + if (!this._lookingGlassShowSignal) { + return; + } + + this._main.lookingGlass.disconnect(this._lookingGlassShowSignal); + this._main.lookingGlass._resize(); + + delete(this._lookingGlassShowSignal); + delete(this._lookingGlassOriginalSize); + delete(this._monitorsChangedSignal); + } + + /** + * set looking glass size + * + * @param {number} width in float + * @param {number} height in float + * + * @returns {void} + */ + lookingGlassSetSize(width, height) + { + let lookingGlass = this._main.createLookingGlass(); + + if (!this._lookingGlassOriginalSize) { + this._lookingGlassOriginalSize = this._lookingGlassGetSize(); + } + + if (this._lookingGlassShowSignal) { + lookingGlass.disconnect(this._lookingGlassShowSignal); + delete(this._lookingGlassShowSignal); + } + + this._lookingGlassShowSignal = lookingGlass.connect('show', () => { + let [, currentHeight] = this._lookingGlassGetSize(); + let [originalWidth, originalHeight] = this._lookingGlassOriginalSize; + + let monitorInfo = this.monitorGetInfo(); + + let dialogWidth + = (width !== null) + ? monitorInfo.width * width + : originalWidth; + + let x = monitorInfo.x + (monitorInfo.width - dialogWidth) / 2; + lookingGlass.set_x(x); + + let keyboardHeight = this._main.layoutManager.keyboardBox.height; + let availableHeight = monitorInfo.height - keyboardHeight; + let dialogHeight + = (height !== null) + ? Math.min(monitorInfo.height * height, availableHeight * 0.9) + : originalHeight; + + let hiddenY = lookingGlass._hiddenY + currentHeight - dialogHeight; + lookingGlass.set_y(hiddenY); + lookingGlass._hiddenY = hiddenY; + + lookingGlass.set_size(dialogWidth, dialogHeight); + }); + + if (!this._monitorsChangedSignal) { + this._monitorsChangedSignal = this._main.layoutManager.connect('monitors-changed', + () => { + this.lookingGlassSetSize(width, height); + }); + } + } + + /** + * show screenshot in window menu + * + * @returns {void} + */ + screenshotInWindowMenuShow() + { + if (this._shellVersion < 42) { + return; + } + + let windowMenuProto = this._windowMenu.WindowMenu.prototype; + + if (windowMenuProto._oldBuildMenu === undefined) { + return; + } + + windowMenuProto._buildMenu = this._originals['WindowMenubuildMenu']; + + delete(windowMenuProto._oldBuildMenu); + } + + /** + * hide screenshot in window menu + * + * @returns {void} + */ + screenshotInWindowMenuHide() + { + if (this._shellVersion < 42) { + return; + } + + let windowMenuProto = this._windowMenu.WindowMenu.prototype; + + if (!this._originals['WindowMenubuildMenu']) { + this._originals['WindowMenubuildMenu'] = windowMenuProto._buildMenu; + } + + if (windowMenuProto._oldBuildMenu === undefined) { + windowMenuProto._oldBuildMenu = this._originals['WindowMenubuildMenu']; + } + + windowMenuProto._buildMenu = function (window) { + this._oldBuildMenu(window); + this.firstMenuItem.hide(); + }; + } + + /** + * set default alt tab window preview size + * + * @returns {void} + */ + altTabWindowPreviewSetDefaultSize() + { + if (!this._originals['altTabWindowPreviewSize']) { + return; + } + + this._altTab.WINDOW_PREVIEW_SIZE = this._originals['altTabWindowPreviewSize']; + } + + /** + * set alt tab window preview size + * + * @param {number} size 1-512 + * + * @returns {void} + */ + altTabWindowPreviewSetSize(size) + { + if (size < 1 || size > 512) { + return; + } + + if (!this._originals['altTabWindowPreviewSize']) { + this._originals['altTabWindowPreviewSize'] = this._altTab.WINDOW_PREVIEW_SIZE; + } + + this._altTab.WINDOW_PREVIEW_SIZE = size; + } + + /** + * set default alt tab small icon size + * + * @returns {void} + */ + altTabSmallIconSetDefaultSize() + { + if (!this._originals['altTabAppIconSizeSmall']) { + return; + } + + this._altTab.APP_ICON_SIZE_SMALL = this._originals['altTabAppIconSizeSmall']; + } + + /** + * set alt tab small icon size + * + * @param {number} size 1-512 + * + * @returns {void} + */ + altTabSmallIconSetSize(size) + { + if (size < 1 || size > 512) { + return; + } + + if (!this._originals['altTabAppIconSizeSmall']) { + this._originals['altTabAppIconSizeSmall'] = this._altTab.APP_ICON_SIZE_SMALL; + } + + this._altTab.APP_ICON_SIZE_SMALL = size; + } + + /** + * set default alt tab icon size + * + * @returns {void} + */ + altTabIconSetDefaultSize() + { + if (!this._originals['altTabAppIconSize']) { + return; + } + + this._altTab.APP_ICON_SIZE = this._originals['altTabAppIconSize']; + } + + /** + * set alt tab icon size + * + * @param {number} size 1-512 + * + * @returns {void} + */ + altTabIconSetSize(size) + { + if (size < 1 || size > 512) { + return; + } + + if (!this._originals['altTabAppIconSize']) { + this._originals['altTabAppIconSize'] = this._altTab.APP_ICON_SIZE; + } + + this._altTab.APP_ICON_SIZE = size; + } +} + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Manager.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Manager.js new file mode 100644 index 0000000..68d1cc0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Manager.js @@ -0,0 +1,1463 @@ +/** + * Manager Library + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +/** + * Apply settings to the GNOME Shell + */ +var Manager = class +{ + /** + * Class Constructor + * + * @param {Object} dependencies + * 'API' instance of lib::API + * 'Settings' instance of Gio::Settings + * @param {number} shellVersion float in major.minor format + */ + constructor(dependencies, shellVersion) + { + this._api = dependencies['API'] || null; + this._settings = dependencies['Settings'] || null; + + this._shellVersion = shellVersion; + } + + /** + * register all signals for settings + * + * @returns {void} + */ + registerSettingsSignals() + { + this._settings.connect('changed::panel', () => { + this._applyPanel(false); + }); + + this._settings.connect('changed::panel-in-overview', () => { + this._applyPanel(false); + }); + + this._settings.connect('changed::search', () => { + this._applySearch(false); + }); + + this._settings.connect('changed::dash', () => { + this._applyDash(false); + }); + + this._settings.connect('changed::osd', () => { + this._applyOSD(false); + }); + + this._settings.connect('changed::workspace-popup', () => { + this._applyWorkspacePopup(false); + }); + + this._settings.connect('changed::workspace', () => { + this._applyWorkspace(false); + }); + + this._settings.connect('changed::background-menu', () => { + this._applyBackgroundMenu(false); + }); + + this._settings.connect('changed::gesture', () => { + this._applyGesture(false); + }); + + this._settings.connect('changed::hot-corner', () => { + this._applyHotCorner(false); + }); + + this._settings.connect('changed::theme', () => { + this._applyTheme(false); + }); + + this._settings.connect('changed::activities-button', () => { + this._applyActivitiesButton(false); + }); + + this._settings.connect('changed::app-menu', () => { + this._applyAppMenu(false); + }); + + this._settings.connect('changed::clock-menu', () => { + this._applyClockMenu(false); + }); + + this._settings.connect('changed::keyboard-layout', () => { + this._applyKeyboardLayout(false); + }); + + this._settings.connect('changed::accessibility-menu', () => { + this._applyAccessibilityMenu(false); + }); + + this._settings.connect('changed::aggregate-menu', () => { + this._applyAggregateMenu(false); + }); + + this._settings.connect('changed::quick-settings', () => { + this._applyQuickSettings(false); + }); + + this._settings.connect('changed::panel-corner-size', () => { + this._applyPanelCornerSize(false); + }); + + this._settings.connect('changed::window-picker-icon', () => { + this._applyWindowPickerIcon(false); + }); + + this._settings.connect('changed::type-to-search', () => { + this._applyTypeToSearch(false); + }); + + this._settings.connect('changed::workspace-switcher-size', () => { + this._applyWorkspaceSwitcherSize(false); + }); + + this._settings.connect('changed::power-icon', () => { + this._applyPowerIcon(false); + }); + + this._settings.connect('changed::top-panel-position', () => { + this._applyTopPanelPosition(false); + }); + + this._settings.connect('changed::panel-arrow', () => { + this._applyPanelArrow(false); + }); + + this._settings.connect('changed::panel-notification-icon', () => { + this._applyPanelNotificationIcon(false); + }); + + this._settings.connect('changed::app-menu-icon', () => { + this._applyAppMenuIcon(false); + }); + + this._settings.connect('changed::app-menu-label', () => { + this._applyAppMenuLabel(false); + }); + + this._settings.connect('changed::clock-menu-position', () => { + this._applyClockMenuPosition(false); + }); + + this._settings.connect('changed::clock-menu-position-offset', () => { + this._applyClockMenuPosition(false); + }); + + this._settings.connect('changed::show-apps-button', () => { + this._applyShowAppsButton(false); + }); + + this._settings.connect('changed::animation', () => { + this._applyAnimation(false); + }); + + this._settings.connect('changed::activities-button-icon-path', () => { + this._applyActivitiesButtonIcon(false); + }); + + this._settings.connect('changed::activities-button-icon-monochrome', () => { + this._applyActivitiesButtonIcon(false); + }); + + this._settings.connect('changed::activities-button-label', () => { + this._applyActivitiesButtonIcon(false); + }); + + this._settings.connect('changed::window-demands-attention-focus', () => { + this._applyWindowDemandsAttentionFocus(false); + }); + + this._settings.connect('changed::dash-icon-size', () => { + this._applyDashIconSize(false); + }); + + this._settings.connect('changed::startup-status', () => { + this._applyStartupStatus(false); + }); + + this._settings.connect('changed::workspaces-in-app-grid', () => { + this._applyWorkspacesInAppGrid(false); + }); + + this._settings.connect('changed::notification-banner-position', () => { + this._applyNotificationBannerPosition(false); + }); + + this._settings.connect('changed::workspace-switcher-should-show', () => { + this._applyWorkspaceSwitcherShouldShow(false); + }); + + this._settings.connect('changed::panel-size', () => { + this._applyPanelSize(false); + }); + + this._settings.connect('changed::panel-button-padding-size', () => { + this._applyPanelButtonPaddingSize(false); + }); + + this._settings.connect('changed::panel-indicator-padding-size', () => { + this._applyPanelIndicatorPaddingSize(false); + }); + + this._settings.connect('changed::window-preview-caption', () => { + this._applyWindowPreviewCaption(false); + }); + + this._settings.connect('changed::window-preview-close-button', () => { + this._applyWindowPreviewCloseButton(false); + }); + + this._settings.connect('changed::workspace-background-corner-size', () => { + this._applyWorkspaceBackgroundCornerSize(false); + }); + + this._settings.connect('changed::workspace-wrap-around', () => { + this._applyWorkspaceWrapAround(false); + }); + + this._settings.connect('changed::ripple-box', () => { + this._applyRippleBox(false); + }); + + this._settings.connect('changed::double-super-to-appgrid', () => { + this._applyDoubleSuperToAppgrid(false); + }); + + this._settings.connect('changed::world-clock', () => { + this._applyWorldClock(false); + }); + + this._settings.connect('changed::weather', () => { + this._applyWeather(false); + }); + + this._settings.connect('changed::calendar', () => { + this._applyCalendar(false); + }); + + this._settings.connect('changed::events-button', () => { + this._applyEventsButton(false); + }); + + this._settings.connect('changed::panel-icon-size', () => { + this._applyPanelIconSize(false); + }); + + this._settings.connect('changed::dash-separator', () => { + this._applyDashSeparator(false); + }); + + this._settings.connect('changed::looking-glass-width', () => { + this._applyLookingGlassSize(false); + }); + + this._settings.connect('changed::looking-glass-height', () => { + this._applyLookingGlassSize(false); + }); + + this._settings.connect('changed::osd-position', () => { + this._applyOSDPosition(false); + }); + + this._settings.connect('changed::window-menu-take-screenshot-button', () => { + this._applyWindowMenuTakeScreenshotButton(false); + }); + + this._settings.connect('changed::alt-tab-window-preview-size', () => { + this._applyAltTabWindowPreviewSize(false); + }); + + this._settings.connect('changed::alt-tab-small-icon-size', () => { + this._applyAltTabSmallIconSize(false); + }); + + this._settings.connect('changed::alt-tab-icon-size', () => { + this._applyAltTabIconSize(false); + }); + } + + /** + * apply everything to the GNOME Shell + * + * @returns {void} + */ + applyAll() + { + this._applyTheme(false); + this._applyPanel(false); + this._applySearch(false); + this._applyDash(false); + this._applyOSD(false); + this._applyWorkspacePopup(false); + this._applyWorkspace(false); + this._applyBackgroundMenu(false); + this._applyGesture(false); + this._applyHotCorner(false); + this._applyActivitiesButton(false); + this._applyAppMenu(false); + this._applyClockMenu(false); + this._applyKeyboardLayout(false); + this._applyAccessibilityMenu(false); + this._applyAggregateMenu(false); + this._applyQuickSettings(false); + this._applyPanelCornerSize(false); + this._applyWindowPickerIcon(false); + this._applyTypeToSearch(false); + this._applyWorkspaceSwitcherSize(false); + this._applyPowerIcon(false); + this._applyTopPanelPosition(false); + this._applyPanelArrow(false); + this._applyPanelNotificationIcon(false); + this._applyAppMenuIcon(false); + this._applyAppMenuLabel(false); + this._applyClockMenuPosition(false); + this._applyShowAppsButton(false); + this._applyAnimation(false); + this._applyActivitiesButtonIcon(false); + this._applyWindowDemandsAttentionFocus(false); + this._applyDashIconSize(false); + this._applyStartupStatus(false); + this._applyWorkspacesInAppGrid(false); + this._applyNotificationBannerPosition(false); + this._applyWorkspaceSwitcherShouldShow(false); + this._applyPanelSize(false); + this._applyPanelButtonPaddingSize(false); + this._applyPanelIndicatorPaddingSize(false); + this._applyWindowPreviewCaption(false); + this._applyWindowPreviewCloseButton(false); + this._applyWorkspaceBackgroundCornerSize(false); + this._applyWorkspaceWrapAround(false); + this._applyRippleBox(false); + this._applyDoubleSuperToAppgrid(false); + this._applyWorldClock(false); + this._applyWeather(false); + this._applyPanelIconSize(false); + this._applyEventsButton(false); + this._applyCalendar(false); + this._applyDashSeparator(false); + this._applyLookingGlassSize(false); + this._applyOSDPosition(false); + this._applyWindowMenuTakeScreenshotButton(false); + this._applyAltTabWindowPreviewSize(false); + this._applyAltTabSmallIconSize(false); + this._applyAltTabIconSize(false); + } + + /** + * revert everything done by this class to the GNOME Shell + * + * @returns {void} + */ + revertAll() + { + this._applyTheme(true); + this._applyPanel(true); + this._applySearch(true); + this._applyDash(true); + this._applyOSD(true); + this._applyWorkspace(true); + this._applyWorkspacePopup(true); + this._applyBackgroundMenu(true); + this._applyGesture(true); + this._applyHotCorner(true); + this._applyActivitiesButton(true); + this._applyAppMenu(true); + this._applyClockMenu(true); + this._applyKeyboardLayout(true); + this._applyAccessibilityMenu(true); + this._applyAggregateMenu(true); + this._applyQuickSettings(true); + this._applyPanelCornerSize(true); + this._applyWindowPickerIcon(true); + this._applyTypeToSearch(true); + this._applyWorkspaceSwitcherSize(true); + this._applyPowerIcon(true); + this._applyTopPanelPosition(true); + this._applyPanelArrow(true); + this._applyPanelNotificationIcon(true); + this._applyAppMenuIcon(true); + this._applyAppMenuLabel(true); + this._applyClockMenuPosition(true); + this._applyShowAppsButton(true); + this._applyAnimation(true); + this._applyActivitiesButtonIcon(true); + this._applyWindowDemandsAttentionFocus(true); + this._applyDashIconSize(true); + this._applyStartupStatus(true); + this._applyWorkspacesInAppGrid(true); + this._applyNotificationBannerPosition(true); + this._applyWorkspaceSwitcherShouldShow(true); + this._applyPanelSize(true); + this._applyPanelButtonPaddingSize(true); + this._applyPanelIndicatorPaddingSize(true); + this._applyWindowPreviewCaption(true); + this._applyWindowPreviewCloseButton(true); + this._applyWorkspaceBackgroundCornerSize(true); + this._applyWorkspaceWrapAround(true); + this._applyRippleBox(true); + this._applyDoubleSuperToAppgrid(true); + this._applyWorldClock(true); + this._applyWeather(true); + this._applyPanelIconSize(true); + this._applyEventsButton(true); + this._applyCalendar(true); + this._applyDashSeparator(true); + this._applyLookingGlassSize(true); + this._applyOSDPosition(true); + this._applyWindowMenuTakeScreenshotButton(true); + this._applyAltTabWindowPreviewSize(true); + this._applyAltTabSmallIconSize(true); + this._applyAltTabIconSize(true); + } + + /** + * apply panel settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanel(forceOriginal) + { + let panel = this._settings.get_boolean('panel'); + let panelInOverview = this._settings.get_boolean('panel-in-overview'); + + if (forceOriginal || panel) { + this._api.panelShow(); + } else { + let mode = (panelInOverview) ? 1 : 0; + this._api.panelHide(mode, 0); + } + } + + /** + * apply search settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applySearch(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('search')) { + this._api.searchEntryShow(false); + } else { + this._api.searchEntryHide(false); + } + } + + /** + * apply type to search settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyTypeToSearch(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('type-to-search')) { + this._api.startSearchEnable(); + } else { + this._api.startSearchDisable(); + } + } + + /** + * apply dash settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyDash(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('dash')) { + this._api.dashShow(); + } else { + this._api.dashHide(); + } + } + + /** + * apply osd settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyOSD(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('osd')) { + this._api.OSDEnable(); + } else { + this._api.OSDDisable(); + } + } + + /** + * apply workspace popup settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspacePopup(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('workspace-popup')) { + this._api.workspacePopupEnable(); + } else { + this._api.workspacePopupDisable(); + } + } + + /** + * apply workspace settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspace(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('workspace')) { + this._api.workspaceSwitcherShow(); + } else { + this._api.workspaceSwitcherHide(); + } + } + + /** + * apply background menu settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyBackgroundMenu(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('background-menu')) { + this._api.backgroundMenuEnable(); + } else { + this._api.backgroundMenuDisable(); + } + } + + /** + * apply gesture settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyGesture(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('gesture')) { + this._api.gestureEnable(); + } else { + this._api.gestureDisable(); + } + } + + /** + * apply hot corner settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyHotCorner(forceOriginal) + { + if (this._shellVersion >= 41) { + return; + } + + if (forceOriginal) { + this._api.hotCornersDefault(); + } else if (!this._settings.get_boolean('hot-corner')) { + this._api.hotCornersDisable(); + } else { + this._api.hotCornersEnable(); + } + } + + /** + * apply theme settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyTheme(forceOriginal) + { + let className = 'just-perfection'; + let fallbackClassName = 'just-perfection-gnome3'; + let fourtySecondGenClassName = 'just-perfection-gnome4x-2nd-gen'; + + if (forceOriginal || !this._settings.get_boolean('theme')) { + this._api.UIStyleClassRemove(className); + this._api.UIStyleClassRemove(fallbackClassName); + this._api.UIStyleClassRemove(fourtySecondGenClassName); + } else { + this._api.UIStyleClassAdd(className); + if (this._shellVersion < 40) { + this._api.UIStyleClassAdd(fallbackClassName); + } + if (this._shellVersion >= 42) { + this._api.UIStyleClassAdd(fourtySecondGenClassName); + } + } + } + + /** + * apply activites button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyActivitiesButton(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('activities-button')) { + this._api.activitiesButtonShow(); + } else { + this._api.activitiesButtonHide(); + } + } + + /** + * apply app menu settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAppMenu(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('app-menu')) { + this._api.appMenuShow(); + } else { + this._api.appMenuHide(); + } + } + + /** + * apply clock menu (aka date menu) settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyClockMenu(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('clock-menu')) { + this._api.dateMenuShow(); + } else { + this._api.dateMenuHide(); + } + } + + /** + * apply keyboard layout settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyKeyboardLayout(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('keyboard-layout')) { + this._api.keyboardLayoutShow(); + } else { + this._api.keyboardLayoutHide(); + } + } + + /** + * apply accessibility menu settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAccessibilityMenu(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('accessibility-menu')) { + this._api.accessibilityMenuShow(); + } else { + this._api.accessibilityMenuHide(); + } + } + + /** + * apply aggregate menu settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAggregateMenu(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('aggregate-menu')) { + this._api.aggregateMenuShow(); + } else { + this._api.aggregateMenuHide(); + } + } + + /** + * apply quick settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyQuickSettings(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('quick-settings')) { + this._api.quickSettingsMenuShow(); + } else { + this._api.quickSettingsMenuHide(); + } + } + + /** + * apply panel corner size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelCornerSize(forceOriginal) + { + let size = this._settings.get_int('panel-corner-size'); + + if (forceOriginal || size === 0) { + this._api.panelCornerSetDefault(); + } else { + this._api.panelCornerSetSize(size - 1); + } + } + + /** + * apply window picker icon settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWindowPickerIcon(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('window-picker-icon')) { + this._api.windowPickerIconEnable(); + } else { + this._api.windowPickerIconDisable(); + } + } + + /** + * apply workspace switcher size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspaceSwitcherSize(forceOriginal) + { + let size = this._settings.get_int('workspace-switcher-size'); + + if (forceOriginal || size === 0) { + this._api.workspaceSwitcherSetDefaultSize(); + } else { + this._api.workspaceSwitcherSetSize(size / 100, false); + } + } + + /** + * apply power icon settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPowerIcon(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('power-icon')) { + this._api.powerIconShow(); + } else { + this._api.powerIconHide(); + } + } + + /** + * apply top panel position settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyTopPanelPosition(forceOriginal) + { + if (forceOriginal || this._settings.get_int('top-panel-position') === 0) { + this._api.panelSetPosition(0); + } else { + this._api.panelSetPosition(1); + } + } + + /** + * apply panel arrow settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelArrow(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('panel-arrow')) { + this._api.panelArrowEnable(); + } else { + this._api.panelArrowDisable(); + } + } + + /** + * apply panel notification icon settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelNotificationIcon(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('panel-notification-icon')) { + this._api.panelNotificationIconEnable(); + } else { + this._api.panelNotificationIconDisable(); + } + } + + /** + * apply app menu icon settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAppMenuIcon(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('app-menu-icon')) { + this._api.appMenuIconEnable(); + } else { + this._api.appMenuIconDisable(); + } + } + + /** + * apply app menu label settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAppMenuLabel(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('app-menu-label')) { + this._api.appMenuLabelEnable(); + } else { + this._api.appMenuLabelDisable(); + } + } + + /** + * apply clock menu position settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyClockMenuPosition(forceOriginal) + { + if (forceOriginal) { + this._api.clockMenuPositionSet(0, 0); + } else { + let pos = this._settings.get_int('clock-menu-position'); + let offset = this._settings.get_int('clock-menu-position-offset'); + this._api.clockMenuPositionSet(pos, offset); + } + } + + /** + * apply show apps button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyShowAppsButton(forceOriginal) + { + if (forceOriginal || this._settings.get_boolean('show-apps-button')) { + this._api.showAppsButtonEnable(); + } else { + this._api.showAppsButtonDisable(); + } + } + + /** + * apply animation settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAnimation(forceOriginal) + { + let animation = this._settings.get_int('animation'); + + let factors = [ + 0.4, // fastest + 0.6, // faster + 0.8, // fast + 1.3, // slow + 1.6, // slower + 2.8, // slowest + ]; + + if (forceOriginal) { + this._api.animationSpeedSetDefault(); + this._api.enableAnimationsSetDefault(); + } else if (animation === 0) { + // disabled + this._api.animationSpeedSetDefault(); + this._api.enableAnimationsSet(false); + } else if (animation === 1) { + // default speed + this._api.animationSpeedSetDefault(); + this._api.enableAnimationsSet(true); + } else if (factors[animation - 2] !== undefined) { + // custom speed + this._api.animationSpeedSet(factors[animation - 2]); + this._api.enableAnimationsSet(true); + } + } + + /** + * apply show apps button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyActivitiesButtonIcon(forceOriginal) + { + let iconPath = this._settings.get_string('activities-button-icon-path'); + let monochrome = this._settings.get_boolean('activities-button-icon-monochrome'); + let label = this._settings.get_boolean('activities-button-label'); + + if (forceOriginal) { + this._api.activitiesButtonRemoveIcon(); + } else { + this._api.activitiesButtonAddIcon(1, iconPath, monochrome, label); + } + } + + /** + * apply window demands attention focus settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWindowDemandsAttentionFocus(forceOriginal) + { + let focus = this._settings.get_boolean('window-demands-attention-focus'); + + if (forceOriginal || !focus) { + this._api.windowDemandsAttentionFocusDisable(); + } else { + this._api.windowDemandsAttentionFocusEnable(); + } + } + + /** + * apply dash icon size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyDashIconSize(forceOriginal) + { + let size = this._settings.get_int('dash-icon-size'); + + if (forceOriginal || size === 0) { + this._api.dashIconSizeSetDefault(); + } else { + this._api.dashIconSizeSet(size); + } + } + + /** + * apply startup status settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyStartupStatus(forceOriginal) + { + let status = this._settings.get_int('startup-status'); + + if (forceOriginal) { + this._api.startupStatusSetDefault(); + } else { + this._api.startupStatusSet(status); + } + } + + /** + * apply workspaces in app grid status settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspacesInAppGrid(forceOriginal) + { + let status = this._settings.get_boolean('workspaces-in-app-grid'); + + if (forceOriginal || status) { + this._api.workspacesInAppGridEnable(); + } else { + this._api.workspacesInAppGridDisable(); + } + } + + /** + * apply notification banner position settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyNotificationBannerPosition(forceOriginal) + { + let pos = this._settings.get_int('notification-banner-position'); + + if (forceOriginal) { + this._api.notificationBannerPositionSetDefault(); + } else { + this._api.notificationBannerPositionSet(pos); + } + } + + /** + * apply workspace switcher should show settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspaceSwitcherShouldShow(forceOriginal) + { + let shouldShow = this._settings.get_boolean('workspace-switcher-should-show'); + + if (forceOriginal || !shouldShow) { + this._api.workspaceSwitcherShouldShowSetDefault(); + } else { + this._api.workspaceSwitcherShouldShow(true); + } + } + + /** + * apply panel size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelSize(forceOriginal) + { + let size = this._settings.get_int('panel-size'); + + if (forceOriginal || size === 0) { + this._api.panelSetDefaultSize(); + } else { + this._api.panelSetSize(size, false); + } + } + + /** + * apply panel button padding size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelButtonPaddingSize(forceOriginal) + { + let size = this._settings.get_int('panel-button-padding-size'); + + if (forceOriginal || size === 0) { + this._api.panelButtonHpaddingSetDefault(); + } else { + this._api.panelButtonHpaddingSizeSet(size - 1); + } + } + + /** + * apply panel indicator padding size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelIndicatorPaddingSize(forceOriginal) + { + let size = this._settings.get_int('panel-indicator-padding-size'); + + if (forceOriginal || size === 0) { + this._api.panelIndicatorPaddingSetDefault(); + } else { + this._api.panelIndicatorPaddingSizeSet(size - 1); + } + } + + /** + * apply window preview caption settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWindowPreviewCaption(forceOriginal) + { + let status = this._settings.get_boolean('window-preview-caption'); + + if (forceOriginal || status) { + this._api.windowPreviewCaptionEnable(); + } else { + this._api.windowPreviewCaptionDisable(); + } + } + + /** + * apply window preview close button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWindowPreviewCloseButton(forceOriginal) + { + let status = this._settings.get_boolean('window-preview-close-button'); + + if (forceOriginal || status) { + this._api.windowPreviewCloseButtonEnable(); + } else { + this._api.windowPreviewCloseButtonDisable(); + } + } + + /** + * apply workspace background corner size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspaceBackgroundCornerSize(forceOriginal) + { + let size = this._settings.get_int('workspace-background-corner-size'); + + if (forceOriginal || size === 0) { + this._api.workspaceBackgroundRadiusSetDefault(); + } else { + this._api.workspaceBackgroundRadiusSet(size - 1); + } + } + + /** + * apply workspace wrap around settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorkspaceWrapAround(forceOriginal) + { + let status = this._settings.get_boolean('workspace-wrap-around'); + + if (forceOriginal || !status) { + this._api.workspaceWraparoundDisable(); + } else { + this._api.workspaceWraparoundEnable(); + } + } + + /** + * apply ripple box settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyRippleBox(forceOriginal) + { + let status = this._settings.get_boolean('ripple-box'); + + if (forceOriginal || status) { + this._api.rippleBoxEnable(); + } else { + this._api.rippleBoxDisable(); + } + } + + /** + * apply double super to appgrid settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyDoubleSuperToAppgrid(forceOriginal) + { + let status = this._settings.get_boolean('double-super-to-appgrid'); + + if (forceOriginal || status) { + this._api.doubleSuperToAppGridEnable(); + } else { + this._api.doubleSuperToAppGridDisable(); + } + } + + /** + * apply world clock settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWorldClock(forceOriginal) + { + let status = this._settings.get_boolean('world-clock'); + + if (forceOriginal || status) { + this._api.worldClocksShow(); + } else { + this._api.worldClocksHide(); + } + } + + /** + * apply weather settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWeather(forceOriginal) + { + let status = this._settings.get_boolean('weather'); + + if (forceOriginal || status) { + this._api.weatherShow(); + } else { + this._api.weatherHide(); + } + } + + /** + * apply calendar settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyCalendar(forceOriginal) + { + let status = this._settings.get_boolean('calendar'); + + if (forceOriginal || status) { + this._api.calendarShow(); + } else { + this._api.calendarHide(); + } + } + + /** + * apply events button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyEventsButton(forceOriginal) + { + let status = this._settings.get_boolean('events-button'); + + if (forceOriginal || status) { + this._api.eventsButtonShow(); + } else { + this._api.eventsButtonHide(); + } + } + + /** + * apply panel icon size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyPanelIconSize(forceOriginal) + { + let size = this._settings.get_int('panel-icon-size'); + + if (forceOriginal || size === 0) { + this._api.panelIconSetDefaultSize(); + } else { + this._api.panelIconSetSize(size); + } + } + + /** + * apply dash separator settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyDashSeparator(forceOriginal) + { + let status = this._settings.get_boolean('dash-separator'); + + if (forceOriginal || status) { + this._api.dashSeparatorShow(); + } else { + this._api.dashSeparatorHide(); + } + } + + /** + * apply looking glass size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyLookingGlassSize(forceOriginal) + { + let widthSize = this._settings.get_int('looking-glass-width'); + let heightSize = this._settings.get_int('looking-glass-height'); + + if (forceOriginal) { + this._api.lookingGlassSetDefaultSize(); + } else { + let width = (widthSize !== 0) ? widthSize / 10 : null; + let height = (heightSize !== 0) ? heightSize / 10 : null; + this._api.lookingGlassSetSize(width, height); + } + } + + /** + * apply osd position settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyOSDPosition(forceOriginal) + { + let pos = this._settings.get_int('osd-position'); + + if (forceOriginal || pos === 0) { + this._api.osdPositionSetDefault(); + } else { + this._api.osdPositionSet(pos - 1); + } + } + + /** + * apply window menu take screenshot button settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyWindowMenuTakeScreenshotButton(forceOriginal) + { + let status = this._settings.get_boolean('window-menu-take-screenshot-button'); + + if (forceOriginal || status) { + this._api.screenshotInWindowMenuShow(); + } else { + this._api.screenshotInWindowMenuHide(); + } + } + + /** + * apply alt tab window preview size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAltTabWindowPreviewSize(forceOriginal) + { + let size = this._settings.get_int('alt-tab-window-preview-size'); + + if (forceOriginal || size === 0) { + this._api.altTabWindowPreviewSetDefaultSize(); + } else { + this._api.altTabWindowPreviewSetSize(size); + } + } + + /** + * apply alt tab small icon size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAltTabSmallIconSize(forceOriginal) + { + let size = this._settings.get_int('alt-tab-small-icon-size'); + + if (forceOriginal || size === 0) { + this._api.altTabSmallIconSetDefaultSize(); + } else { + this._api.altTabSmallIconSetSize(size); + } + } + + /** + * apply alt tab icon size settings + * + * @param {boolean} forceOriginal force original shell setting + * + * @returns {void} + */ + _applyAltTabIconSize(forceOriginal) + { + let size = this._settings.get_int('alt-tab-icon-size'); + + if (forceOriginal || size === 0) { + this._api.altTabIconSetDefaultSize(); + } else { + this._api.altTabIconSetSize(size); + } + } +} + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js new file mode 100644 index 0000000..24eede5 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js @@ -0,0 +1,805 @@ +/** + * Prefs Library + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +/** + * prefs widget for showing prefs window + */ +var Prefs = class +{ + /** + * class constructor + * + * @param {Object} dependencies + * 'Builder' instance of Gtk::Builder + * 'Settings' instance of Gio::Settings + * 'GObjectBindingFlags' instance of GObject::BindingFlags + * 'Gtk' reference to Gtk + * 'Gdk' reference to Gdk + * 'Gio' reference to Gio + * 'GLib' reference to GLib + * @param {PrefsKeys.PrefsKeys} prefsKeys instance of PrefsKeys + * @param {number} shellVersion float in major.minor format + */ + constructor(dependencies, prefsKeys, shellVersion) + { + this._settings = dependencies['Settings'] || null; + this._builder = dependencies['Builder'] || null; + this._gobjectBindingFlags = dependencies['GObjectBindingFlags'] || null; + this._gtk = dependencies['Gtk'] || null; + this._gdk = dependencies['Gdk'] || null; + this._gio = dependencies['Gio'] || null; + this._glib = dependencies['GLib'] || null; + + this._prefsKeys = prefsKeys; + this._shellVersion = shellVersion; + this._gtkVersion = (this._gtk) ? this._gtk.get_major_version() : 3; + + /** + * whether it is called for adwaita window + * + * @member {boolean} + */ + this._isAdw = false; + + /** + * holds Gtk.DropDown items that are + * created inside this._convertComboBoxTextToDropDown() + * object key is widget id + * + * @member {Object} + */ + this._dropdowns = {}; + + /** + * initial window size + * + * @member {number} + */ + this._windowWidth = 600; + this._windowHeight = 750; + + /** + * initial window size for adw + * + * @member {number} + */ + this._windowWidthAdw = 600; + this._windowHeightAdw = 650; + + /** + * holds all profile names + * + * @member {string} + */ + this._profiles = [ + 'default', + 'minimal', + 'superminimal', + ]; + + /** + * holds all required urls + * + * @member {Object} + */ + this._url = { + bug_report: 'https://gitlab.gnome.org/jrahmatzadeh/just-perfection/-/issues', + patreon: 'https://www.patreon.com/justperfection', + }; + } + + /** + * fill prefs window + * + * @param {string} UIFolderPath folder path to ui folder + * @param {string} binFolderPath bin folder path + * @param {string} gettextDomain gettext domain + * + * @returns {void} + */ + fillPrefsWindow(window, UIFolderPath, binFolderPath, gettextDomain) + { + this._isAdw = true; + + // changing the order here can change the elements order in ui + let uiFilenames = [ + 'profile', + 'visibility', + 'icons', + 'behavior', + 'customize', + ]; + + this._builder.set_translation_domain(gettextDomain); + for (let uiFilename of uiFilenames) { + this._builder.add_from_file(`${UIFolderPath}/adw/${uiFilename}.ui`); + } + + for (let uiFilename of uiFilenames) { + let page = this._builder.get_object(uiFilename); + window.add(page); + } + + this._setValues(); + this._guessProfile(); + this._onlyShowSupportedRows(); + this._registerAllSignals(window); + + this._setWindowSize(window); + + window.search_enabled = true; + } + + /** + * get prefs widget + * + * @param {string} UIFolderPath folder path to ui folder + * @param {string} binFolderPath bin folder path + * @param {string} gettextDomain gettext domain + * + * @returns {Object} + */ + getPrefsWidget(UIFolderPath, binFolderPath, gettextDomain) + { + this._isAdw = false; + + // changing the order here can change the elements order in ui + let uiFilenames = [ + 'main', + 'no-results-found', + 'profile', + 'override', + 'visibility', + 'icons', + 'behavior', + 'customize', + ]; + + // profile is not supported on GNOME Shell 3.x + if (this._shellVersion < 40) { + uiFilenames.splice(uiFilenames.indexOf('profile'), 1); + } + + this._builder.set_translation_domain(gettextDomain); + for (let uiFilename of uiFilenames) { + this._builder.add_from_file(`${UIFolderPath}/${uiFilename}.ui`); + } + + let obj = this._builder.get_object('main_prefs'); + let prefsBox = this._builder.get_object('main_prefs_in_box'); + + for (let uiFilename of uiFilenames) { + if (uiFilename === 'main') { + continue; + } + let elementId = uiFilename.replace(/-/g, '_'); + let elm = this._builder.get_object(elementId); + if (this._gtkVersion === 3) { + prefsBox.add(elm); + } else { + prefsBox.append(elm); + } + } + + this._convertComboBoxTextToDropDown(); + this._fixIconObjects(); + this._setValues(); + this._guessProfile(); + + this._onlyShowSupportedRows(); + + obj.connect('realize', () => { + + let window = (this._gtkVersion === 3) ? obj.get_toplevel() : obj.get_root(); + + this._setWindowSize(window); + + // csd + let headerBar = this._builder.get_object('header_bar'); + let csdMenu = this._builder.get_object('csd_menu'); + window.set_titlebar(headerBar); + if (this._gtkVersion === 3) { + headerBar.set_title('Just Perfection'); + headerBar.set_show_close_button(true); + } + headerBar.pack_end(csdMenu); + + this._registerAllSignals(window); + }); + + return obj; + } + + /** + * set window size + * + * @param {Gtk.Window|Adw.PreferencesWindow} window prefs window + * + * @returns {void} + */ + _setWindowSize(window) + { + let [pmWidth, pmHeight, pmScale] = this._getPrimaryMonitorInfo(); + let sizeTolerance = 50; + let width = (this._isAdw) ? this._windowWidthAdw : this._windowWidth; + let height = (this._isAdw) ? this._windowHeightAdw : this._windowHeight; + + if ( + (pmWidth/pmScale) - sizeTolerance >= width && + (pmHeight/pmScale) - sizeTolerance >= height + ) { + if (!this._isAdw) { + window.default_width = width; + } + window.set_default_size(width, height); + if (this._gtkVersion === 3) { + window.resize(width, height); + } + } + } + + /** + * get primary monitor info + * + * @returns {Array} [width, height, scale] + */ + _getPrimaryMonitorInfo() + { + let display = this._gdk.Display.get_default(); + + let pm + = (this._gtkVersion === 3) + ? display.get_monitor(0) + : display.get_monitors().get_item(0); + + if (!pm) { + return [700, 500, 1]; + } + + let geo = pm.get_geometry(); + let scale = pm.get_scale_factor(); + + return [geo.width, geo.height, scale]; + } + + /** + * fix images that holding icons for GTK4 + * + * @returns {void} + */ + _fixIconObjects() + { + if (this._gtkVersion === 3 || this._isAdw) { + return; + } + + let icons = [ + 'menu_icon', + 'search_icon', + ]; + + icons.forEach(id => { + let elm = this._builder.get_object(id); + let parent = elm.get_parent(); + let iconName = elm.get_icon_name(); + let iconSize = elm.get_icon_size(); + + parent.icon_name = iconName; + parent.icon_size = iconSize; + }); + } + + /** + * convert all comboboxes to drop down and hold them inside this._dropdowns + * + * @returns {void} + */ + _convertComboBoxTextToDropDown() + { + if (this._gtkVersion === 3 || this._isAdw) { + return; + } + + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + if (key.widgetType === 'GtkComboBoxText') { + let widget = this._builder.get_object(key.widgetId); + let parent = widget.get_parent(); + + let items = []; + widget.set_active(0); + let selectedIndex = 0; + while (widget.get_active_text() !== null) { + items.push(widget.get_active_text()); + selectedIndex++; + widget.set_active(selectedIndex); + } + + let dropdown = this._gtk.DropDown.new_from_strings(items); + + this._prefsKeys.deleteKey(key.id); + + let newKey = this._prefsKeys.setKey( + key.category, + key.name, + 'GtkDropDown', + key.supported, + key.profiles, + key.maps + ); + + this._dropdowns[newKey.widgetId] = dropdown; + + dropdown.set_valign(this._gtk.Align.CENTER); + + widget.hide(); + parent.append(dropdown); + } + } + } + + /** + * register all signals + * + * @param {Gtk.Window} window prefs dialog + * + * @returns {void} + */ + _registerAllSignals(window) + { + this._registerKeySignals(); + this._registerSearchSignals(window); + this._registerFileChooserSignals(window); + this._registerProfileSignals(); + this._registerActionSignals(window); + } + + /** + * register signals of all prefs keys + * + * @returns {void} + */ + _registerKeySignals() + { + // all available keys + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + + switch (key.widgetType) { + + case 'GtkSwitch': + this._builder.get_object(key.widgetId).connect('state-set', (w) => { + this._settings.set_boolean(key.name, w.get_active()); + this._guessProfile(); + }); + break; + + case 'GtkComboBoxText': + this._builder.get_object(key.widgetId).connect('changed', (w) => { + let index = w.get_active(); + let value = (index in key.maps) ? key.maps[index] : index; + this._settings.set_int(key.name, value); + this._guessProfile(); + }); + break; + + case 'GtkDropDown': + this._dropdowns[key.widgetId].connect('notify::selected-item', (w) => { + let index = w.get_selected(); + let value = (index in key.maps) ? key.maps[index] : index; + this._settings.set_int(key.name, value); + this._guessProfile(); + }); + break; + + case 'AdwActionRow': + this._builder.get_object(key.widgetId).connect('notify::selected-item', (w) => { + let index = w.get_selected(); + let value = (index in key.maps) ? key.maps[index] : index; + this._settings.set_int(key.name, value); + this._guessProfile(); + }); + break; + + case 'GtkEntry': + this._builder.get_object(key.widgetId).connect('changed', (w) => { + this._settings.set_string(key.name, w.text); + this._guessProfile(); + }); + break; + } + } + } + + /** + * register search signals + * + * @param {Gtk.Window} window prefs dialog + * + * @returns {void} + */ + _registerSearchSignals(window) + { + if (this._isAdw) { + return; + } + + let searchEntry = this._builder.get_object('search_entry'); + searchEntry.connect('changed', (w) => { + this._search(w.get_text()); + }); + + let searchBar = this._builder.get_object('searchbar'); + if (this._gtkVersion === 3) { + window.connect('key-press-event', (w, e) => { + return searchBar.handle_event(e); + }); + } else { + searchBar.set_key_capture_widget(window); + } + + let searchBtn = this._builder.get_object('search_togglebutton'); + searchBtn.bind_property('active', searchBar, 'search-mode-enabled', + this._gobjectBindingFlags.BIDIRECTIONAL); + + searchBar.connect_entry(searchEntry); + } + + /** + * register file chooser signals + * + * @param {Gtk.Window} window prefs dialog + * + * @returns {void} + */ + _registerFileChooserSignals(window) + { + let fileChooser = this._builder.get_object('file_chooser'); + let activitiesButtonIconPath = { + button: this._builder.get_object('activities_button_icon_path_button'), + entry: this._builder.get_object('activities_button_icon_path_entry'), + empty: this._builder.get_object('activities_button_icon_path_empty_button'), + }; + + activitiesButtonIconPath['entry'].connect('changed', (w) => { + this._setFileChooserValue('activities_button_icon_path', w.text, true); + }); + + activitiesButtonIconPath['empty'].connect('clicked', () => { + this._setFileChooserValue('activities_button_icon_path', ''); + }); + + activitiesButtonIconPath['button'].connect('clicked', (w) => { + this.currentFileChooserEntry = activitiesButtonIconPath['entry']; + + let uri = activitiesButtonIconPath['entry'].text; + let file = this._gio.File.new_for_uri(uri); + let fileExists = file.query_exists(null); + if (fileExists) { + let fileParent = file.get_parent(); + fileChooser.set_current_folder( + (this._gtkVersion === 3) ? fileParent.get_path() : fileParent + ); + } + + fileChooser.set_transient_for(window); + fileChooser.show(); + }); + + fileChooser.connect('response', (w, response) => { + if (response !== this._gtk.ResponseType.ACCEPT) { + return; + } + let fileURI = w.get_file().get_uri(); + this.currentFileChooserEntry.text = fileURI; + }); + } + + /** + * register profile signals + * + * @returns {void} + */ + _registerProfileSignals() + { + for (let profile of this._profiles) { + let profileElm = this._builder.get_object(`profile_${profile}`); + if (!profileElm) { + break; + } + profileElm.connect('clicked', (w) => { + this._setValues(profile); + }); + } + } + + /** + * register action signals + * + * @param {Gtk.Window} window prefs dialog + * + * @returns {void} + */ + _registerActionSignals(window) + { + if (this._isAdw) { + return + } + + let actionGroup = new this._gio.SimpleActionGroup(); + + let action1 = new this._gio.SimpleAction({name: 'show-bug-report'}); + action1.connect('activate', () => { + this._openURI(window, this._url.bug_report); + }); + actionGroup.add_action(action1); + + let action2 = new this._gio.SimpleAction({name: 'show-patreon'}); + action2.connect('activate', () => { + this._openURI(window, this._url.patreon); + }); + actionGroup.add_action(action2); + + window.insert_action_group('prefs', actionGroup); + } + + /** + * open uri + * + * @param {string} uri uri to open + * @param {Gtk.Window} window prefs dialog + * + * @returns {void} + */ + _openURI(window, uri) + { + if (this._gtkVersion === 3) { + this._gtk.show_uri_on_window(window, uri, this._gdk.CURRENT_TIME); + return; + } + + this._gtk.show_uri(window, uri, this._gdk.CURRENT_TIME); + } + + /** + * can check all current values and guess the profile based on the values + * + * @returns {void} + */ + _guessProfile() + { + let totalCount = 0; + let matchCount = {}; + + for (let profile of this._profiles) { + matchCount[profile] = 0; + } + + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + + if (!key.supported) { + continue; + } + + let value; + + switch (key.widgetType) { + case 'GtkSwitch': + case 'GtkComboBoxText': + value = this._builder.get_object(key.widgetId).get_active(); + break; + case 'AdwActionRow': + value = this._builder.get_object(key.widgetId).get_selected(); + break; + case 'GtkDropDown': + value = this._dropdowns[key.widgetId].get_selected(); + break; + case 'GtkEntry': + value = this._builder.get_object(key.widgetId).text; + break; + default: + value = ''; + continue; + } + + for (let profile of this._profiles) { + if (key.profiles[profile] === value) { + matchCount[profile]++; + } + } + + totalCount++; + } + + let currentProfile = 'custom'; + for (let profile of this._profiles) { + if (matchCount[profile] === totalCount) { + currentProfile = profile; + break; + } + } + + let profileElm = this._builder.get_object(`profile_${currentProfile}`); + if (profileElm) { + profileElm.set_active(true); + } + } + + /** + * set file chooser button value + * + * @param {string} id element starter id + * @param {string} uri file address + * @param {bool} entrySetBefore whether file chooser entry value has been set before + * + * @returns {void} + */ + _setFileChooserValue(id, uri, entrySetBefore = false) + { + let preview = this._builder.get_object(`${id}_preview`); + let emptyButton = this._builder.get_object(`${id}_empty_button`); + let entry = this._builder.get_object(`${id}_entry`); + + if (!entry) { + return; + } + + let file = this._gio.File.new_for_uri(uri); + let fileExists = file.query_exists(null); + let uriPrepared = (fileExists) ? uri : ''; + + let visible = uriPrepared !== ''; + + if (!entrySetBefore) { + entry.text = uriPrepared; + } + emptyButton.visible = visible; + + preview.clear(); + + if (fileExists) { + let gicon = this._gio.icon_new_for_string(file.get_path()); + if (this._gtkVersion === 3) { + preview.set_from_gicon(gicon, 1); + } else { + preview.set_from_gicon(gicon); + } + } else { + preview.icon_name = 'document-open-symbolic'; + } + } + + /** + * set values for all elements + * + * @param {string} profile profile name or null for get it from gsettings + * + * @returns {void} + */ + _setValues(profile) + { + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + + let elm + = (key.widgetType === 'GtkDropDown') + ? this._dropdowns[key.widgetId] + : this._builder.get_object(key.widgetId); + + switch (key.widgetType) { + + case 'GtkSwitch': + let value + = (profile) + ? key.profiles[profile] + : this._settings.get_boolean(key.name); + + elm.set_active(value); + break; + + case 'GtkComboBoxText': + case 'GtkDropDown': + case 'AdwActionRow': + let index + = (profile) + ? key.profiles[profile] + : this._settings.get_int(key.name); + + for (let k in key.maps) { + if (key.maps[k] === index) { + index = k; + break; + } + } + if (key.widgetType === 'GtkDropDown' || key.widgetType === 'AdwActionRow') { + elm.set_selected(index); + } else { + elm.set_active(index); + } + break; + + case 'GtkEntry': + let text + = (profile) + ? key.profiles[profile] + : this._settings.get_string(key.name); + + elm.text = text; + this._setFileChooserValue(key.id, elm.text); + break; + } + } + } + + /** + * apply all supported keys to the elements + * + * @returns {void} + */ + _onlyShowSupportedRows() + { + if (!this._isAdw) { + this._search(''); + return; + } + + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + let row = this._builder.get_object(`${key.id}_row`); + let visible = key.supported; + row.visible = visible; + } + } + + /** + * search the query + * + * @param {string} q query + * + * @returns {void} + */ + _search(q) + { + let categories = {}; + let noResultsFoundVisibility = true; + + let profile = this._builder.get_object('profile'); + if (profile) { + profile.visible = (q === '') ? true : false; + } + + for (let [, key] of Object.entries(this._prefsKeys.keys)) { + + if (categories[key.category] === undefined) { + categories[key.category] = 0; + } + + let text = this._builder.get_object(`${key.id}_txt`).get_text(); + let row = this._builder.get_object(`${key.id}_row`); + + let visible = key.supported && text.toLowerCase().includes(q); + + row.visible = visible; + + if (visible) { + categories[key.category]++; + noResultsFoundVisibility = false; + } + } + + // hide the category when nothing is visible in it + for (var category in categories) { + let titleElm = this._builder.get_object(`${category}_title`); + let frameElm = this._builder.get_object(`${category}_frame`); + let visible = categories[category] > 0; + + titleElm.visible = visible; + frameElm.visible = visible; + } + + let notFound = this._builder.get_object('no_results_found'); + notFound.visible = noResultsFoundVisibility; + } +}; + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js new file mode 100644 index 0000000..0150ca8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js @@ -0,0 +1,888 @@ +/** + * PrefsKeys Library + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +/** + * prefs keys + */ +var PrefsKeys = class +{ + /** + * class constructor + * + * @param {number} shellVersion float in major.minor format + * @param {boolean} isAdw whether the current prefs is using libadwaita + */ + constructor(shellVersion, isAdw) + { + this._shellVersion = shellVersion; + this._isAdw = isAdw; + + /** + * holds all keys generated by this.setKey() + * + * @member {Object} + */ + this.keys = {}; + + this._setDefaults(); + } + + /** + * set all default keys + * + * @returns {void} + */ + _setDefaults() + { + this.setKey( + 'visibility', + 'panel', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'panel-in-overview', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'activities-button', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'app-menu', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'app-menu-label', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'clock-menu', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'keyboard-layout', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'accessibility-menu', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'aggregate-menu', + 'GtkSwitch', + this._shellVersion < 43, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'quick-settings', + 'GtkSwitch', + this._shellVersion >= 43, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'search', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'dash', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'dash-separator', + 'GtkSwitch', + this._shellVersion >= 40, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'osd', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'workspace-popup', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'workspace', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'background-menu', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'show-apps-button', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'workspaces-in-app-grid', + 'GtkSwitch', + this._shellVersion >= 40, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'window-preview-caption', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'window-preview-close-button', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'ripple-box', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'visibility', + 'world-clock', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'weather', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'calendar', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'events-button', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'visibility', + 'window-menu-take-screenshot-button', + 'GtkSwitch', + this._shellVersion >= 42, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'app-menu-icon', + 'GtkSwitch', + true, + { + default: true, + minimal: false, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'panel-notification-icon', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'power-icon', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'window-picker-icon', + 'GtkSwitch', + this._shellVersion >= 40, + { + default: true, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'icons', + 'panel-arrow', + 'GtkSwitch', + this._shellVersion < 40, + { + default: true, + minimal: false, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'activities-button-icon-path', + 'GtkEntry', + true, + { + default: '', + minimal: '', + superminimal: '', + } + ); + + this.setKey( + 'icons', + 'activities-button-icon-monochrome', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'icons', + 'activities-button-label', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'behavior', + 'type-to-search', + 'GtkSwitch', + true, + { + default: true, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'behavior', + 'hot-corner', + 'GtkSwitch', + this._shellVersion < 41, + { + default: false, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'behavior', + 'gesture', + 'GtkSwitch', + this._shellVersion < 40, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'behavior', + 'window-demands-attention-focus', + 'GtkSwitch', + true, + { + default: false, + minimal: true, + superminimal: true, + } + ); + + this.setKey( + 'behavior', + 'workspace-switcher-should-show', + 'GtkSwitch', + this._shellVersion >= 40, + { + default: false, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'behavior', + 'startup-status', + 'GtkComboBoxText', + this._shellVersion >= 40, + { + default: 1, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'behavior', + 'workspace-wrap-around', + 'GtkSwitch', + true, + { + default: false, + minimal: false, + superminimal: false, + } + ); + + this.setKey( + 'behavior', + 'double-super-to-appgrid', + 'GtkSwitch', + this._shellVersion >= 40, + { + default: true, + minimal: true, + superminimal: false, + } + ); + + this.setKey( + 'customize', + 'workspace-background-corner-size', + 'GtkComboBoxText', + this._shellVersion >= 40, + { + default: 0, + minimal: 0, + superminimal: 15, + } + ); + + this.setKey( + 'customize', + 'top-panel-position', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'panel-corner-size', + 'GtkComboBoxText', + this._shellVersion < 42, + { + default: 0, + minimal: 1, + superminimal: 1, + } + ); + + this.setKey( + 'customize', + 'clock-menu-position', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'clock-menu-position-offset', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'workspace-switcher-size', + 'GtkComboBoxText', + this._shellVersion >= 40, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'animation', + 'GtkComboBoxText', + true, + { + default: 1, + minimal: 1, + superminimal: 1, + } + ); + + this.setKey( + 'customize', + 'dash-icon-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 1, + superminimal: 0, + }, + { + '1': 32, + '2': 48, + '3': 64, + } + ); + + this.setKey( + 'customize', + 'notification-banner-position', + 'GtkComboBoxText', + true, + { + default: 1, + minimal: 1, + superminimal: 1, + } + ); + + this.setKey( + 'customize', + 'panel-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'panel-button-padding-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'panel-indicator-padding-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'panel-icon-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'osd-position', + 'GtkComboBoxText', + this._shellVersion >= 42, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'looking-glass-width', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'looking-glass-height', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + } + ); + + this.setKey( + 'customize', + 'alt-tab-window-preview-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + }, + { + '0': 0, + '1': 32, + '2': 64, + '3': 128, + '4': 256, + '5': 512, + } + ); + + this.setKey( + 'customize', + 'alt-tab-small-icon-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + }, + { + '0': 0, + '1': 32, + '2': 64, + '3': 128, + '4': 256, + '5': 512, + } + ); + + this.setKey( + 'customize', + 'alt-tab-icon-size', + 'GtkComboBoxText', + true, + { + default: 0, + minimal: 0, + superminimal: 0, + }, + { + '0': 0, + '1': 32, + '2': 64, + '3': 128, + '4': 256, + '5': 512, + } + ); + + this.setKey( + 'override', + 'theme', + 'GtkSwitch', + true, + { + default: false, + minimal: true, + superminimal: true, + } + ); + } + + /** + * set key + * + * @param {string} category possible values: + * - visibility + * - icons + * - behavior + * - customize + * - override + * @param {string} name should be the same as gsettings key name + * @param {string} widgetType gtk widget type like 'GtkSwitch'. + * @param {boolean} supported whether supported in the current shell + * @param {Object} profiles values for each profile. for example: + * {default: true, minimal: false} + * @param {Object} [maps] for example for combobox you can specify + * if the index is 1 go use 32 as value: + * {1 : 32} + * + * @returns {Object} key object that has been set + */ + setKey(category, name, widgetType, supported, profiles, maps) + { + if (this._isAdw && widgetType === 'GtkComboBoxText') { + widgetType = 'AdwActionRow'; + } + + let id = name.replace(/-/g, '_'); + let widgetName = widgetType.toLowerCase().replace('gtk', ''); + let widgetId = (widgetType === 'AdwActionRow') ? `${id}_row` : `${id}_${widgetName}`; + + if (maps === undefined) { + maps = {}; + } + + this.keys[id] = { + category, + widgetType, + name, + id, + widgetId, + supported, + profiles, + maps, + } + + return this.keys[id]; + } + + /** + * delete key + * + * @param {string} id key id + * + * @returns {void} + */ + deleteKey(id) + { + delete(this.keys[id]); + } +}; + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..706de7d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..7ce1ea8 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..506632b Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..e9cd8c9 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..db269c4 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..c843dcb Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..f702c55 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..ad47052 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..22cd72a Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..fb49dcf Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..af5bafe Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..2eb9dd2 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..2bec88d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..568075c Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..a0a168a Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..c50ff2b Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo new file mode 100644 index 0000000..293bfb3 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/metadata.json new file mode 100644 index 0000000..fa3761b --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/metadata.json @@ -0,0 +1,18 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Tweak Tool to Customize GNOME Shell, Change the Behavior and Disable UI Elements\n\n- Accessibility Menu Visibility\n- Activities Button Icon Visibility\n- Activities button Visibility\n- Alt Tab Icon Size\n- Alt Tab Window Preview Icon Size\n- Alt Tab Window Preview Size\n- Always Show Workspace Switcher on Dynamic Workspaces (40, 41, 42)\n- Animation Speed or Disable it\n- App Gesture (3.36, 3.38)\n- Applications Button Visibility\n- App Menu Icon Visibility\n- App Menu Label Visibility\n- App Menu Visibility\n- Background Menu Visibility\n- Calendar Visibility\n- Clock Menu Position\n- Clock Menu Visibility\n- Dash Icon Size\n- Dash Separator Visibility (40, 41, 42)\n- Dash Visibility\n- Disable Type to Search\n- Double Super Key to App Grid\n- Events in Clock Menu Visibility\n- GNOME Shell Theme Override\n- Hot Corner (3.36, 3.38, 40)\n- Keyboard Layout Visibility\n- Looking Glass Size\n- Notification Banner Position\n- OSD Position\n- OSD Visibility\n- Panel Arrow Visibility (3.36, 3.38)\n- Panel Button Padding Size\n- Panel Height\n- Panel icon size \n- Panel Indicator Padding Size\n- Panel Notification icon Visibility\n- Panel Position\n- Panel Round Corner Size (3.36, 3.38, 40, 41)\n- Panel Visibility\n- Panel Visibility in Overview\n- Power Icon Visibility\n- Quick Settings Menu Visibility (43)\n- Ripple Box\n- Search Visibility\n- Startup Status(40, 41, 42)\n- System Menu (Aggregate Menu) Visibility (3.36, 3.38, 40, 41, 42)\n- Take Screenshot Button in Window Menu Visibility\n- Weather Visibility\n- Window Demands Attention Focus\n- Window Picker Caption Visibility\n- Window Picker Close Button Visibility\n- Window Picker Icon (40, 41, 42)\n- Workspace Background Corner Size in Overview (40, 41, 42)\n- Workspace Popup Visibility\n- Workspaces in app grid Visibility (40, 41, 42)\n- Workspace Switcher Size (40, 41, 42)\n- Workspace Switcher Visibility\n- Workspace Wraparound\n- World Clock Visibility", + "gettext-domain": "just-perfection", + "name": "Just Perfection", + "settings-schema": "org.gnome.shell.extensions.just-perfection", + "shell-version": [ + "3.36", + "3.38", + "40", + "41", + "42", + "43" + ], + "url": "https://gitlab.gnome.org/jrahmatzadeh/just-perfection", + "uuid": "just-perfection-desktop@just-perfection", + "version": 22 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/prefs.js new file mode 100644 index 0000000..aa355a8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/prefs.js @@ -0,0 +1,79 @@ +/** + * Prefs Dialog + * + * @author Javad Rahmatzadeh + * @copyright 2020-2022 + * @license GPL-3.0-only + */ + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +const {Prefs, PrefsKeys} = Me.imports.lib.Prefs; +const {Gtk, Gdk, Gio, GLib, GObject} = imports.gi; + +const Config = imports.misc.config; +const shellVersion = parseFloat(Config.PACKAGE_VERSION); + +const gettextDomain = Me.metadata['gettext-domain']; +const UIFolderPath = Me.dir.get_child('ui').get_path(); +const binFolderPath = Me.dir.get_child('bin').get_path(); + +/** + * prefs widget + * + * @param {boolean} isAdw whether it is calling for adw ui + * + * @returns {Prefs.Prefs} + */ +function getPrefs(isAdw) +{ + let builder = new Gtk.Builder(); + let settings = ExtensionUtils.getSettings(); + let prefsKeys = new PrefsKeys.PrefsKeys(shellVersion, isAdw); + + return new Prefs.Prefs( + { + Builder: builder, + Settings: settings, + GObjectBindingFlags: GObject.BindingFlags, + Gtk, + Gdk, + Gio, + GLib, + }, + prefsKeys, + shellVersion + ); +} + +/** + * prefs initiation + * + * @returns {void} + */ +function init() +{ + ExtensionUtils.initTranslations(); +} + +/** + * fill prefs window + * + * @returns {Adw.PreferencesWindow} + */ +function fillPreferencesWindow(window) +{ + getPrefs(true).fillPrefsWindow(window, UIFolderPath, binFolderPath, gettextDomain); +} + +/** + * prefs widget + * + * @returns {Gtk.Widget} + */ +function buildPrefsWidget() +{ + return getPrefs(false).getPrefsWidget(UIFolderPath, binFolderPath, gettextDomain); +} + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled new file mode 100644 index 0000000..a010d98 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml new file mode 100644 index 0000000..9d31e01 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml @@ -0,0 +1,407 @@ + + + + + + + true + Panel + Panel Visibility Status + + + + false + Panel in Overview + Panel in Overview Visibility Status + + + + true + Background Menu + Background Menu Status + + + + true + Search Box + Search Box Visibility Status + + + + true + Workspace Switcher + Workspace Switcher Visibility Status + + + + true + Dash + Dash Visibility Status + + + + true + OSD + OSD Visibility Status + + + + true + Workspace Popup + Workspace Popup Visibility Status + + + + true + Gesture + Gesture Status + + + + false + Hot Corner + Hot Corner Status + + + + false + Theme + Theme Status + + + + true + Activities Button + Activities Button Visibility Status + + + + true + App Menu + App Menu Visibility Status + + + + true + App Menu Icon + App Menu Icon Visibility Status + + + + true + App Menu Label + App Menu Label Visibility Status + + + + true + Clock Menu + Clock Menu Visibility Status + + + + true + Panel Notification Icon + Panel Notification Icon Visibility Status + + + + true + Keyboard Layout + Keyboard Layout Visibility Status + + + + true + Accessibility Menu + Accessibility Menu Visibility Status + + + + true + Aggregate Menu + Aggregate Menu Visibility Status + + + + true + Quick Settings Menu + Quick Settings Visibility Status + + + + true + Power Icon + Power Icon Visibility Status + + + + true + Panel Arrow + Panel Arrow Visibility Status + + + + true + Window Picker Icon + Window Picker Icon Visiblity + + + + true + Type to Search + Type to Search Behavior + + + + 0 + + 0 means use Shell theme, 1 means no border, 2 - 61 means border size + Panel Corner Size + + + + 0 + + Workspace Switcher Size in percent, 0 means use default size + Workspace Switcher Size + + + + 0 + + Top Panel Position + Top Panel Position Status + + + + 0 + + 0 means center, 1 means right, 2 means left + Clock Menu Position Status + + + + 0 + + 0 means start of the position + Clock Menu Position Offset + + + + true + Show Apps Button Visiblity + Show Apps Button Visiblity Status + + + + 1 + + 0 means disabled, 1 means default speed, animation speed otherwise + Animation Status + + + + '' + Activities Button Icon Path + Activities Button Icon Path + + + + true + Activities Button Monochrome Icon Style + Activities Button Monochrome Icon Style Status + + + + true + Activities Button Label Visiblity + Activities Button Label Visiblity Status + + + + false + Window Demands Attention Focus + Window Demands Attention Focus Status + + + + 0 + + 0 means default, 16, 22, 24, 32, 48, 64 + Dash Icon Size + + + + 1 + + 0 means desktop, 1 means overview + Startup Status + + + + true + Workspaces Visiblity in App Grid + Workspaces Visiblity in App Grid Status + + + + 1 + + 0: top start, 1: top center, 2: top end, 3: bottom start, 4: bottom center, 5: bottom end + Notification Banner Position + + + + false + Always Show Workspaces Switcher + Always Show Workspace Switcher Status + + + + 0 + + 0 means use Shell theme, 1 - 61 means size in pixels + Panel Size + + + + 0 + + 0 means use Shell theme, 1 means no padding, 2 - 61 means padding size + Panel Button Padding Size + + + + 0 + + 0 means use Shell theme, 1 means no padding, 2 - 61 means padding size + Panel Indicator Padding Size + + + + true + Window Preview Caption + Window Preview Caption Status + + + + true + Window Preview Close Button + Window Preview Close Button Status + + + + 0 + + 0 means use default shell size, 1 means no radius, 2 - 61 means radius size + Workspace Background Corner Size + + + + false + Workspace Wrap Around + Workspace Wrap Around Status + + + + true + Ripple Box + Ripple Box Status + + + + true + Double Supper To App Grid + Double Supper To App Grid Status + + + + true + World Clock Visibility in Clock Menu + World Clock Visibility Status + + + + true + Weather Visibility in Clock Menu + Weather Visibility Status + + + + true + Events Button Visibility in Clock Menu + Events Button Visibility Status + + + + true + Calendar Visibility in Clock Menu + Calendar Visibility Status + + + + 0 + + 0 means use Shell theme, 1 - 60 means panel icon size + Panel Icon Size + + + + true + Dash Separator Visibility + Dash Separator Visibility Status + + + + 0 + + Width Size in percent, 0 means use default size + Looking Glass Width size + + + + 0 + + Height Size in percent, 0 means use default size + Looking Glass Height size + + + + 0 + + OSD Position + OSD Position Status + + + + true + Window Menu Take Screenshot Button Visibility + Window Menu Take Screenshot Button Visibility Status + + + + 0 + + 0 means default size + Alt Tab Window Preview Size + + + + 0 + + 0 means default size + Alt Tab Small Icon Size (Window Preview Icon Size) + + + + 0 + + 0 means default size + Alt Tab Icon Size + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/stylesheet.css new file mode 100644 index 0000000..cce8de7 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/stylesheet.css @@ -0,0 +1,809 @@ +.just-perfection +{ + font-size: small; +} + +.just-perfection .workspace-animation +{ + background-color: black; +} + +.just-perfection .window-clone-border +{ + border: 5px solid #004AC7; + border-radius: 16px; + box-shadow: inset 0 0 0 0 #004AC7; +} + +.just-perfection .window-caption +{ + color: #ffffff; + background-color: #004AC7; + font-size: small; + font-weight: normal; +} + +.just-perfection .window-close +{ + background-image: url("bin/close-button.svg"); + background-size: 24px; + height: 24px; + width: 24px; + background-color: transparent; + color: transparent; + border-radius: 24px; + border: 0 solid #1b6acb; +} + +.just-perfection .switcher-popup +{ + padding: 8px; + spacing: 24px; + font-size: small; +} + +.just-perfection .switcher-list +{ + color: #eeeeec; + background-color: rgba(0, 0, 0, .99); + border: 0 solid rgba(255, 255, 255, .16); + border-radius: 15px; + padding: 12px; + box-shadow: none; +} + +.just-perfection .switcher-list .item-box +{ + padding: 8px; + border-radius: 14px; + border: 1px solid transparent; +} + +.just-perfection .switcher-list .item-box:outlined +{ + border: 0; + background-color: rgba(255, 255, 255, .1); + box-shadow: inset 0 2px 2px 0 rgba(0, 0, 0, .4); +} + +.just-perfection .switcher-list .item-box:selected +{ + background-color: #404040; + color: #eeeeec; +} + +.just-perfection .switcher-list .thumbnail-box +{ + padding: 2px; + spacing: 6px; +} + +.just-perfection .switcher-list .thumbnail +{ + width: 256px; +} + +.just-perfection .switcher-list .separator +{ + width: 1px; + background: #272727; +} + +.just-perfection .switcher-list .switcher-list-item-container +{ + spacing: 12px; +} + +.just-perfection .workspace-switcher-container +{ + background-color: rgba(0, 0, 0, .7); + box-shadow: none; + padding: 3px; + border: 0; + border-radius: 3px; +} + +.just-perfection .workspace-switcher +{ + background: transparent; + border: none; + border-radius: 0; + padding: 0; + spacing: 4px; +} + +.just-perfection.just-perfection-gnome4x-2nd-gen .workspace-switcher +{ + background: rgba(0, 0, 0, .7); + box-shadow: none; + border: none; + border-radius: 5px; + padding: 0; + spacing: 4px; +} + +.just-perfection .ws-switcher-indicator, +.just-perfection .ws-switcher-indicator:active +{ + background: transparent; + background-color: rgba(255, 255, 255, .02); + height: 8px; + width: 20px; + border: 0; + border-radius: 2px; + padding: 2px; + margin: 5px; +} + +.just-perfection .ws-switcher-indicator:active +{ + background-color: rgba(255, 255, 255, .8); +} + +.just-perfection .ws-switcher-box +{ + background: transparent; + background-color: rgba(255, 255, 255, .02); + height: 10px; + background-size: 0; + border: 0; + border-radius: 1px; +} + +.just-perfection .ws-switcher-active-up, +.just-perfection .ws-switcher-active-down, +.just-perfection .ws-switcher-active-left, +.just-perfection .ws-switcher-active-right +{ + height: 10px; + background-color: rgba(255, 255, 255, .8); + border: 0; + border-radius: 1px; +} + +.just-perfection .osd-window +{ + background-color: rgba(0, 0, 0, 1); + border: 0; + border-radius: 8px; + padding: 10px; + box-shadow: none; +} + +.just-perfection.just-perfection-gnome4x-2nd-gen .osd-window StIcon +{ + width: 22px; + height: 22px; +} + +.just-perfection .search-entry +{ + caret-color: white; + selection-background-color: #008bff; + selected-color: white; + padding: 10px; + color: white; + background-color: rgba(0, 0, 0, .5); + border: 0; + border-radius: 10px; + box-shadow: none; +} + +.just-perfection .search-entry:focus +{ + background-color: rgba(0, 0, 0, .6); +} + +.just-perfection .search-entry .search-entry-icon +{ + icon-size: 18px; + padding: 0 0; + color: rgba(255, 255, 255, .5); +} + +.just-perfection .search-section .search-section-separator +{ + height: 1px; + background-color: rgba(255, 255, 255, .1); +} + +.just-perfection .search-section-content +{ + spacing: 0; + border-radius: 0; + border: 0; + box-shadow: none; + background: none; + text-shadow: none; + color: rgba(255, 255, 255, .98); +} + +.just-perfection.just-perfection-gnome3 #dash +{ + background-color: rgba(0, 0, 0, .4); + padding: 5px 0; + border: 0; + border-radius: 0 15px 15px 0; +} + +.just-perfection.just-perfection-gnome3 #dash:rtl +{ + padding: 5px 0; + border-radius: 15px 0 0 15px; +} + +.just-perfection.just-perfection-gnome3 .workspace-thumbnails +{ + spacing: 20px; + padding: 20px; + padding-right: 0; + margin: 0; + border-radius: 15px 0 0 15px; + border: 0; + color: rgba(255, 255, 255, .85); + background-color: rgba(0, 0, 0, .5); +} + +.just-perfection.just-perfection-gnome3 .workspace-thumbnail-indicator +{ + border: 0; + border-bottom: 2px solid transparent; + border-color: #0860f2; + padding: 0; + padding-bottom: 2px; + border-radius: 0; +} + +.just-perfection .tile-preview +{ + background-color: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.6); + border-radius: 0; +} + +.just-perfection-api-no-search #overview +{ + spacing: 0; +} + +.just-perfection-api-no-search .overview-controls +{ + padding-top: 36px; + padding-bottom: 36px; +} + +.just-perfection-api-gnome3.just-perfection-api-no-workspace .window-picker +{ + /* 100% won't work but when the px is more than the maximum width it will be 100%*/ + width: 100000px; +} + +.just-perfection-api-gnome40.just-perfection-api-no-workspace .workspace-thumbnails, +.just-perfection-api-gnome41.just-perfection-api-no-workspace .workspace-thumbnails, +.just-perfection-api-gnome42.just-perfection-api-no-workspace .workspace-thumbnails, +.just-perfection-api-gnome43.just-perfection-api-no-workspace .workspace-thumbnails, +.just-perfection-api-gnome40.just-perfection-api-no-workspace .workspace-thumbnail-indicator, +.just-perfection-api-gnome41.just-perfection-api-no-workspace .workspace-thumbnail-indicator, +.just-perfection-api-gnome42.just-perfection-api-no-workspace .workspace-thumbnail-indicator, +.just-perfection-api-gnome43.just-perfection-api-no-workspace .workspace-thumbnail-indicator +{ + /* we use scale=0 which is giving us the same width and height as 0 */ + /* spacing: 0; */ + /* width: 0; */ + /* height: 0; */ + padding: 0; + margin: 0; + border: 0; +} + +.just-perfection-api-gnome3.just-perfection-api-no-panel .search-entry +{ + margin-top: 10px; + margin-bottom: 10px; +} + +.just-perfection-api-gnome40.just-perfection-api-no-panel .search-entry, +.just-perfection-api-gnome41.just-perfection-api-no-panel .search-entry, +.just-perfection-api-gnome42.just-perfection-api-no-panel .search-entry, +.just-perfection-api-gnome43.just-perfection-api-no-panel .search-entry +{ + margin-top: 30px; +} + +/* commented because the icon will be shown when the window is getting dragged */ +/* icon-dropshadow isn't specific to the window picker icon but that's a quick fix for now */ +/* .just-perfection-api-no-window-picker-icon .workspaces-view StIcon */ +.just-perfection-api-no-window-picker-icon .icon-dropshadow +{ + width: 0; + height: 0; + padding: 0; +} + +.just-perfection-api-no-power-icon .power-status StIcon +{ + width: 0; + height: 0; + padding: 0; +} + +.just-perfection-api-gnome3.just-perfection-api-type-to-search #overview +{ + margin-top: 23px; +} + +.just-perfection-api-gnome3.just-perfection-api-type-to-search #overview .search-entry +{ + margin-bottom: 23px; +} + +.just-perfection-api-bottom-panel #overview +{ + margin-bottom: 24px; +} + +.just-perfection-api-bottom-panel .popup-menu.panel-menu +{ + margin-bottom: 0; +} + +.just-perfection-api-bottom-panel.just-perfection-api-no-panel #overview +{ + margin-bottom: 0; +} + +.just-perfection-api-no-panel-arrow .panel-button .popup-menu-arrow +{ + width: 0; + height: 0; +} + +/** + * we shouldn't mess with GNOME Shell theme + * so styling with css for each size is more proper + */ +.just-perfection-api-panel-corner0 #panel .panel-corner { -panel-corner-radius: 0px; } +.just-perfection-api-panel-corner1 #panel .panel-corner { -panel-corner-radius: 1px; } +.just-perfection-api-panel-corner2 #panel .panel-corner { -panel-corner-radius: 2px; } +.just-perfection-api-panel-corner3 #panel .panel-corner { -panel-corner-radius: 3px; } +.just-perfection-api-panel-corner4 #panel .panel-corner { -panel-corner-radius: 4px; } +.just-perfection-api-panel-corner5 #panel .panel-corner { -panel-corner-radius: 5px; } +.just-perfection-api-panel-corner6 #panel .panel-corner { -panel-corner-radius: 6px; } +.just-perfection-api-panel-corner7 #panel .panel-corner { -panel-corner-radius: 7px; } +.just-perfection-api-panel-corner8 #panel .panel-corner { -panel-corner-radius: 8px; } +.just-perfection-api-panel-corner9 #panel .panel-corner { -panel-corner-radius: 9px; } +.just-perfection-api-panel-corner10 #panel .panel-corner { -panel-corner-radius: 10px; } +.just-perfection-api-panel-corner11 #panel .panel-corner { -panel-corner-radius: 11px; } +.just-perfection-api-panel-corner12 #panel .panel-corner { -panel-corner-radius: 12px; } +.just-perfection-api-panel-corner13 #panel .panel-corner { -panel-corner-radius: 13px; } +.just-perfection-api-panel-corner14 #panel .panel-corner { -panel-corner-radius: 14px; } +.just-perfection-api-panel-corner15 #panel .panel-corner { -panel-corner-radius: 15px; } +.just-perfection-api-panel-corner16 #panel .panel-corner { -panel-corner-radius: 16px; } +.just-perfection-api-panel-corner17 #panel .panel-corner { -panel-corner-radius: 17px; } +.just-perfection-api-panel-corner18 #panel .panel-corner { -panel-corner-radius: 18px; } +.just-perfection-api-panel-corner19 #panel .panel-corner { -panel-corner-radius: 19px; } +.just-perfection-api-panel-corner20 #panel .panel-corner { -panel-corner-radius: 20px; } +.just-perfection-api-panel-corner21 #panel .panel-corner { -panel-corner-radius: 21px; } +.just-perfection-api-panel-corner22 #panel .panel-corner { -panel-corner-radius: 22px; } +.just-perfection-api-panel-corner23 #panel .panel-corner { -panel-corner-radius: 23px; } +.just-perfection-api-panel-corner24 #panel .panel-corner { -panel-corner-radius: 24px; } +.just-perfection-api-panel-corner25 #panel .panel-corner { -panel-corner-radius: 25px; } +.just-perfection-api-panel-corner26 #panel .panel-corner { -panel-corner-radius: 26px; } +.just-perfection-api-panel-corner27 #panel .panel-corner { -panel-corner-radius: 27px; } +.just-perfection-api-panel-corner28 #panel .panel-corner { -panel-corner-radius: 28px; } +.just-perfection-api-panel-corner29 #panel .panel-corner { -panel-corner-radius: 29px; } +.just-perfection-api-panel-corner30 #panel .panel-corner { -panel-corner-radius: 30px; } +.just-perfection-api-panel-corner31 #panel .panel-corner { -panel-corner-radius: 31px; } +.just-perfection-api-panel-corner32 #panel .panel-corner { -panel-corner-radius: 32px; } +.just-perfection-api-panel-corner33 #panel .panel-corner { -panel-corner-radius: 33px; } +.just-perfection-api-panel-corner34 #panel .panel-corner { -panel-corner-radius: 34px; } +.just-perfection-api-panel-corner35 #panel .panel-corner { -panel-corner-radius: 35px; } +.just-perfection-api-panel-corner36 #panel .panel-corner { -panel-corner-radius: 36px; } +.just-perfection-api-panel-corner37 #panel .panel-corner { -panel-corner-radius: 37px; } +.just-perfection-api-panel-corner38 #panel .panel-corner { -panel-corner-radius: 38px; } +.just-perfection-api-panel-corner39 #panel .panel-corner { -panel-corner-radius: 39px; } +.just-perfection-api-panel-corner40 #panel .panel-corner { -panel-corner-radius: 40px; } +.just-perfection-api-panel-corner41 #panel .panel-corner { -panel-corner-radius: 41px; } +.just-perfection-api-panel-corner42 #panel .panel-corner { -panel-corner-radius: 42px; } +.just-perfection-api-panel-corner43 #panel .panel-corner { -panel-corner-radius: 43px; } +.just-perfection-api-panel-corner44 #panel .panel-corner { -panel-corner-radius: 44px; } +.just-perfection-api-panel-corner45 #panel .panel-corner { -panel-corner-radius: 45px; } +.just-perfection-api-panel-corner46 #panel .panel-corner { -panel-corner-radius: 46px; } +.just-perfection-api-panel-corner47 #panel .panel-corner { -panel-corner-radius: 47px; } +.just-perfection-api-panel-corner48 #panel .panel-corner { -panel-corner-radius: 48px; } +.just-perfection-api-panel-corner49 #panel .panel-corner { -panel-corner-radius: 49px; } +.just-perfection-api-panel-corner50 #panel .panel-corner { -panel-corner-radius: 50px; } +.just-perfection-api-panel-corner51 #panel .panel-corner { -panel-corner-radius: 51px; } +.just-perfection-api-panel-corner52 #panel .panel-corner { -panel-corner-radius: 52px; } +.just-perfection-api-panel-corner53 #panel .panel-corner { -panel-corner-radius: 53px; } +.just-perfection-api-panel-corner54 #panel .panel-corner { -panel-corner-radius: 54px; } +.just-perfection-api-panel-corner55 #panel .panel-corner { -panel-corner-radius: 55px; } +.just-perfection-api-panel-corner56 #panel .panel-corner { -panel-corner-radius: 56px; } +.just-perfection-api-panel-corner57 #panel .panel-corner { -panel-corner-radius: 57px; } +.just-perfection-api-panel-corner58 #panel .panel-corner { -panel-corner-radius: 58px; } +.just-perfection-api-panel-corner59 #panel .panel-corner { -panel-corner-radius: 59px; } +.just-perfection-api-panel-corner60 #panel .panel-corner { -panel-corner-radius: 60px; } + +.just-perfection-api-no-panel-notification-icon .clock-display StIcon +{ + width: 0; + height: 0; + padding: 0; +} + +.just-perfection-api-no-panel-notification-icon .clock-display-box +{ + padding: 0; + spacing: 0; +} + +.just-perfection-api-no-app-menu-icon .app-menu-icon +{ + width: 0; + height: 0; + margin: 0; +} + +.just-perfection-api-no-show-apps-button .show-apps, +.just-perfection-api-no-show-apps-button .show-apps StIcon +{ + width: 0; + margin: 0; + spacing: 0; +} + +.just-perfection-gnome3.just-perfection-api-no-show-apps-button .show-apps, +.just-perfection-gnome3.just-perfection-api-no-show-apps-button .show-apps StIcon +{ + height: 0; +} + +.just-perfection-api-activities-button-icon, +.just-perfection-api-activities-button-icon-monochrome +{ + /* commented because padding would be enough since we are only using */ + /* one element inside the box */ + /* -natural-hpadding: 6px; */ + /* -minimum-hpadding: 6px; */ + padding-right: 6px; + padding-left: 0; +} + +.just-perfection-api-activities-button-icon-monochrome +{ + -st-icon-style: symbolic; +} + +.just-perfection-api-activities-button-no-label .just-perfection-api-activities-button-icon, +.just-perfection-api-activities-button-no-label .just-perfection-api-activities-button-icon-monochrome +{ + -natural-hpadding: 0; + -minimum-hpadding: 0; + padding-right: 0; + padding-left: 0; +} + +.just-perfection-api-dash-icon-size16 #dash StIcon { height: 16px; width: 16px; } +.just-perfection-api-dash-icon-size22 #dash StIcon { height: 22px; width: 22px; } +.just-perfection-api-dash-icon-size24 #dash StIcon { height: 24px; width: 24px; } +.just-perfection-api-dash-icon-size32 #dash StIcon { height: 32px; width: 32px; } +.just-perfection-api-dash-icon-size48 #dash StIcon { height: 48px; width: 48px; } +.just-perfection-api-dash-icon-size64 #dash StIcon { height: 64px; width: 64px; } + + +.just-perfection-api-panel-button-padding-size0 .panel-button { -natural-hpadding: 0px; -minimum-hpadding: 0px; } +.just-perfection-api-panel-button-padding-size1 .panel-button { -natural-hpadding: 1px; -minimum-hpadding: 1px; } +.just-perfection-api-panel-button-padding-size2 .panel-button { -natural-hpadding: 2px; -minimum-hpadding: 2px; } +.just-perfection-api-panel-button-padding-size3 .panel-button { -natural-hpadding: 3px; -minimum-hpadding: 3px; } +.just-perfection-api-panel-button-padding-size4 .panel-button { -natural-hpadding: 4px; -minimum-hpadding: 4px; } +.just-perfection-api-panel-button-padding-size5 .panel-button { -natural-hpadding: 5px; -minimum-hpadding: 5px; } +.just-perfection-api-panel-button-padding-size6 .panel-button { -natural-hpadding: 6px; -minimum-hpadding: 6px; } +.just-perfection-api-panel-button-padding-size7 .panel-button { -natural-hpadding: 7px; -minimum-hpadding: 7px; } +.just-perfection-api-panel-button-padding-size8 .panel-button { -natural-hpadding: 8px; -minimum-hpadding: 8px; } +.just-perfection-api-panel-button-padding-size9 .panel-button { -natural-hpadding: 9px; -minimum-hpadding: 9px; } +.just-perfection-api-panel-button-padding-size10 .panel-button { -natural-hpadding: 10px; -minimum-hpadding: 10px; } +.just-perfection-api-panel-button-padding-size11 .panel-button { -natural-hpadding: 11px; -minimum-hpadding: 11px; } +.just-perfection-api-panel-button-padding-size12 .panel-button { -natural-hpadding: 12px; -minimum-hpadding: 12px; } +.just-perfection-api-panel-button-padding-size13 .panel-button { -natural-hpadding: 13px; -minimum-hpadding: 13px; } +.just-perfection-api-panel-button-padding-size14 .panel-button { -natural-hpadding: 14px; -minimum-hpadding: 14px; } +.just-perfection-api-panel-button-padding-size15 .panel-button { -natural-hpadding: 15px; -minimum-hpadding: 15px; } +.just-perfection-api-panel-button-padding-size16 .panel-button { -natural-hpadding: 16px; -minimum-hpadding: 16px; } +.just-perfection-api-panel-button-padding-size17 .panel-button { -natural-hpadding: 17px; -minimum-hpadding: 17px; } +.just-perfection-api-panel-button-padding-size18 .panel-button { -natural-hpadding: 18px; -minimum-hpadding: 18px; } +.just-perfection-api-panel-button-padding-size19 .panel-button { -natural-hpadding: 19px; -minimum-hpadding: 19px; } +.just-perfection-api-panel-button-padding-size20 .panel-button { -natural-hpadding: 20px; -minimum-hpadding: 20px; } +.just-perfection-api-panel-button-padding-size21 .panel-button { -natural-hpadding: 21px; -minimum-hpadding: 21px; } +.just-perfection-api-panel-button-padding-size22 .panel-button { -natural-hpadding: 22px; -minimum-hpadding: 22px; } +.just-perfection-api-panel-button-padding-size23 .panel-button { -natural-hpadding: 23px; -minimum-hpadding: 23px; } +.just-perfection-api-panel-button-padding-size24 .panel-button { -natural-hpadding: 24px; -minimum-hpadding: 24px; } +.just-perfection-api-panel-button-padding-size25 .panel-button { -natural-hpadding: 25px; -minimum-hpadding: 25px; } +.just-perfection-api-panel-button-padding-size26 .panel-button { -natural-hpadding: 26px; -minimum-hpadding: 26px; } +.just-perfection-api-panel-button-padding-size27 .panel-button { -natural-hpadding: 27px; -minimum-hpadding: 27px; } +.just-perfection-api-panel-button-padding-size28 .panel-button { -natural-hpadding: 28px; -minimum-hpadding: 28px; } +.just-perfection-api-panel-button-padding-size29 .panel-button { -natural-hpadding: 29px; -minimum-hpadding: 29px; } +.just-perfection-api-panel-button-padding-size30 .panel-button { -natural-hpadding: 30px; -minimum-hpadding: 30px; } +.just-perfection-api-panel-button-padding-size31 .panel-button { -natural-hpadding: 31px; -minimum-hpadding: 31px; } +.just-perfection-api-panel-button-padding-size32 .panel-button { -natural-hpadding: 32px; -minimum-hpadding: 32px; } +.just-perfection-api-panel-button-padding-size33 .panel-button { -natural-hpadding: 33px; -minimum-hpadding: 33px; } +.just-perfection-api-panel-button-padding-size34 .panel-button { -natural-hpadding: 34px; -minimum-hpadding: 34px; } +.just-perfection-api-panel-button-padding-size35 .panel-button { -natural-hpadding: 35px; -minimum-hpadding: 35px; } +.just-perfection-api-panel-button-padding-size36 .panel-button { -natural-hpadding: 36px; -minimum-hpadding: 36px; } +.just-perfection-api-panel-button-padding-size37 .panel-button { -natural-hpadding: 37px; -minimum-hpadding: 37px; } +.just-perfection-api-panel-button-padding-size38 .panel-button { -natural-hpadding: 38px; -minimum-hpadding: 38px; } +.just-perfection-api-panel-button-padding-size39 .panel-button { -natural-hpadding: 39px; -minimum-hpadding: 39px; } +.just-perfection-api-panel-button-padding-size40 .panel-button { -natural-hpadding: 40px; -minimum-hpadding: 40px; } +.just-perfection-api-panel-button-padding-size41 .panel-button { -natural-hpadding: 41px; -minimum-hpadding: 41px; } +.just-perfection-api-panel-button-padding-size42 .panel-button { -natural-hpadding: 42px; -minimum-hpadding: 42px; } +.just-perfection-api-panel-button-padding-size43 .panel-button { -natural-hpadding: 43px; -minimum-hpadding: 43px; } +.just-perfection-api-panel-button-padding-size44 .panel-button { -natural-hpadding: 44px; -minimum-hpadding: 44px; } +.just-perfection-api-panel-button-padding-size45 .panel-button { -natural-hpadding: 45px; -minimum-hpadding: 45px; } +.just-perfection-api-panel-button-padding-size46 .panel-button { -natural-hpadding: 46px; -minimum-hpadding: 46px; } +.just-perfection-api-panel-button-padding-size47 .panel-button { -natural-hpadding: 47px; -minimum-hpadding: 47px; } +.just-perfection-api-panel-button-padding-size48 .panel-button { -natural-hpadding: 48px; -minimum-hpadding: 48px; } +.just-perfection-api-panel-button-padding-size49 .panel-button { -natural-hpadding: 49px; -minimum-hpadding: 49px; } +.just-perfection-api-panel-button-padding-size50 .panel-button { -natural-hpadding: 50px; -minimum-hpadding: 50px; } +.just-perfection-api-panel-button-padding-size51 .panel-button { -natural-hpadding: 51px; -minimum-hpadding: 51px; } +.just-perfection-api-panel-button-padding-size52 .panel-button { -natural-hpadding: 52px; -minimum-hpadding: 52px; } +.just-perfection-api-panel-button-padding-size53 .panel-button { -natural-hpadding: 53px; -minimum-hpadding: 53px; } +.just-perfection-api-panel-button-padding-size54 .panel-button { -natural-hpadding: 54px; -minimum-hpadding: 54px; } +.just-perfection-api-panel-button-padding-size55 .panel-button { -natural-hpadding: 55px; -minimum-hpadding: 55px; } +.just-perfection-api-panel-button-padding-size56 .panel-button { -natural-hpadding: 56px; -minimum-hpadding: 56px; } +.just-perfection-api-panel-button-padding-size57 .panel-button { -natural-hpadding: 57px; -minimum-hpadding: 57px; } +.just-perfection-api-panel-button-padding-size58 .panel-button { -natural-hpadding: 58px; -minimum-hpadding: 58px; } +.just-perfection-api-panel-button-padding-size59 .panel-button { -natural-hpadding: 59px; -minimum-hpadding: 59px; } +.just-perfection-api-panel-button-padding-size60 .panel-button { -natural-hpadding: 60px; -minimum-hpadding: 60px; } + +.just-perfection-api-no-window-caption .window-caption +{ + spacing: 0; + background-color: transparent; + border-radius: 0; + border: 0; + padding: 0; + font-size: 0; +} + +.just-perfection-api-workspace-background-radius-size0 .workspace-background { border-radius: 0; } +.just-perfection-api-workspace-background-radius-size1 .workspace-background { border-radius: 1px; } +.just-perfection-api-workspace-background-radius-size2 .workspace-background { border-radius: 2px; } +.just-perfection-api-workspace-background-radius-size3 .workspace-background { border-radius: 3px; } +.just-perfection-api-workspace-background-radius-size4 .workspace-background { border-radius: 4px; } +.just-perfection-api-workspace-background-radius-size5 .workspace-background { border-radius: 5px; } +.just-perfection-api-workspace-background-radius-size6 .workspace-background { border-radius: 6px; } +.just-perfection-api-workspace-background-radius-size7 .workspace-background { border-radius: 7px; } +.just-perfection-api-workspace-background-radius-size8 .workspace-background { border-radius: 8px; } +.just-perfection-api-workspace-background-radius-size9 .workspace-background { border-radius: 9px; } +.just-perfection-api-workspace-background-radius-size10 .workspace-background { border-radius: 10px; } +.just-perfection-api-workspace-background-radius-size11 .workspace-background { border-radius: 11px; } +.just-perfection-api-workspace-background-radius-size12 .workspace-background { border-radius: 12px; } +.just-perfection-api-workspace-background-radius-size13 .workspace-background { border-radius: 13px; } +.just-perfection-api-workspace-background-radius-size14 .workspace-background { border-radius: 14px; } +.just-perfection-api-workspace-background-radius-size15 .workspace-background { border-radius: 15px; } +.just-perfection-api-workspace-background-radius-size16 .workspace-background { border-radius: 16px; } +.just-perfection-api-workspace-background-radius-size17 .workspace-background { border-radius: 17px; } +.just-perfection-api-workspace-background-radius-size18 .workspace-background { border-radius: 18px; } +.just-perfection-api-workspace-background-radius-size19 .workspace-background { border-radius: 19px; } +.just-perfection-api-workspace-background-radius-size20 .workspace-background { border-radius: 20px; } +.just-perfection-api-workspace-background-radius-size21 .workspace-background { border-radius: 21px; } +.just-perfection-api-workspace-background-radius-size22 .workspace-background { border-radius: 22px; } +.just-perfection-api-workspace-background-radius-size23 .workspace-background { border-radius: 23px; } +.just-perfection-api-workspace-background-radius-size24 .workspace-background { border-radius: 24px; } +.just-perfection-api-workspace-background-radius-size25 .workspace-background { border-radius: 25px; } +.just-perfection-api-workspace-background-radius-size26 .workspace-background { border-radius: 26px; } +.just-perfection-api-workspace-background-radius-size27 .workspace-background { border-radius: 27px; } +.just-perfection-api-workspace-background-radius-size28 .workspace-background { border-radius: 28px; } +.just-perfection-api-workspace-background-radius-size29 .workspace-background { border-radius: 29px; } +.just-perfection-api-workspace-background-radius-size30 .workspace-background { border-radius: 30px; } +.just-perfection-api-workspace-background-radius-size31 .workspace-background { border-radius: 31px; } +.just-perfection-api-workspace-background-radius-size32 .workspace-background { border-radius: 32px; } +.just-perfection-api-workspace-background-radius-size33 .workspace-background { border-radius: 33px; } +.just-perfection-api-workspace-background-radius-size34 .workspace-background { border-radius: 34px; } +.just-perfection-api-workspace-background-radius-size35 .workspace-background { border-radius: 35px; } +.just-perfection-api-workspace-background-radius-size36 .workspace-background { border-radius: 36px; } +.just-perfection-api-workspace-background-radius-size37 .workspace-background { border-radius: 37px; } +.just-perfection-api-workspace-background-radius-size38 .workspace-background { border-radius: 38px; } +.just-perfection-api-workspace-background-radius-size39 .workspace-background { border-radius: 39px; } +.just-perfection-api-workspace-background-radius-size40 .workspace-background { border-radius: 40px; } +.just-perfection-api-workspace-background-radius-size41 .workspace-background { border-radius: 41px; } +.just-perfection-api-workspace-background-radius-size42 .workspace-background { border-radius: 42px; } +.just-perfection-api-workspace-background-radius-size43 .workspace-background { border-radius: 43px; } +.just-perfection-api-workspace-background-radius-size44 .workspace-background { border-radius: 44px; } +.just-perfection-api-workspace-background-radius-size45 .workspace-background { border-radius: 45px; } +.just-perfection-api-workspace-background-radius-size46 .workspace-background { border-radius: 46px; } +.just-perfection-api-workspace-background-radius-size47 .workspace-background { border-radius: 47px; } +.just-perfection-api-workspace-background-radius-size48 .workspace-background { border-radius: 48px; } +.just-perfection-api-workspace-background-radius-size49 .workspace-background { border-radius: 49px; } +.just-perfection-api-workspace-background-radius-size50 .workspace-background { border-radius: 50px; } +.just-perfection-api-workspace-background-radius-size51 .workspace-background { border-radius: 51px; } +.just-perfection-api-workspace-background-radius-size52 .workspace-background { border-radius: 52px; } +.just-perfection-api-workspace-background-radius-size53 .workspace-background { border-radius: 53px; } +.just-perfection-api-workspace-background-radius-size54 .workspace-background { border-radius: 54px; } +.just-perfection-api-workspace-background-radius-size55 .workspace-background { border-radius: 55px; } +.just-perfection-api-workspace-background-radius-size56 .workspace-background { border-radius: 56px; } +.just-perfection-api-workspace-background-radius-size57 .workspace-background { border-radius: 57px; } +.just-perfection-api-workspace-background-radius-size58 .workspace-background { border-radius: 58px; } +.just-perfection-api-workspace-background-radius-size59 .workspace-background { border-radius: 59px; } +.just-perfection-api-workspace-background-radius-size60 .workspace-background { border-radius: 60px; } + +.just-perfection-api-panel-indicator-padding-size0 .panel-status-indicators-box { spacing: 0; } +.just-perfection-api-panel-indicator-padding-size1 .panel-status-indicators-box { spacing: 1px; } +.just-perfection-api-panel-indicator-padding-size2 .panel-status-indicators-box { spacing: 2px; } +.just-perfection-api-panel-indicator-padding-size3 .panel-status-indicators-box { spacing: 3px; } +.just-perfection-api-panel-indicator-padding-size4 .panel-status-indicators-box { spacing: 4px; } +.just-perfection-api-panel-indicator-padding-size5 .panel-status-indicators-box { spacing: 5px; } +.just-perfection-api-panel-indicator-padding-size6 .panel-status-indicators-box { spacing: 6px; } +.just-perfection-api-panel-indicator-padding-size7 .panel-status-indicators-box { spacing: 7px; } +.just-perfection-api-panel-indicator-padding-size8 .panel-status-indicators-box { spacing: 8px; } +.just-perfection-api-panel-indicator-padding-size9 .panel-status-indicators-box { spacing: 9px; } +.just-perfection-api-panel-indicator-padding-size10 .panel-status-indicators-box { spacing: 10px; } +.just-perfection-api-panel-indicator-padding-size11 .panel-status-indicators-box { spacing: 11px; } +.just-perfection-api-panel-indicator-padding-size12 .panel-status-indicators-box { spacing: 12px; } +.just-perfection-api-panel-indicator-padding-size13 .panel-status-indicators-box { spacing: 13px; } +.just-perfection-api-panel-indicator-padding-size14 .panel-status-indicators-box { spacing: 14px; } +.just-perfection-api-panel-indicator-padding-size15 .panel-status-indicators-box { spacing: 15px; } +.just-perfection-api-panel-indicator-padding-size16 .panel-status-indicators-box { spacing: 16px; } +.just-perfection-api-panel-indicator-padding-size17 .panel-status-indicators-box { spacing: 17px; } +.just-perfection-api-panel-indicator-padding-size18 .panel-status-indicators-box { spacing: 18px; } +.just-perfection-api-panel-indicator-padding-size19 .panel-status-indicators-box { spacing: 19px; } +.just-perfection-api-panel-indicator-padding-size20 .panel-status-indicators-box { spacing: 20px; } +.just-perfection-api-panel-indicator-padding-size21 .panel-status-indicators-box { spacing: 21px; } +.just-perfection-api-panel-indicator-padding-size22 .panel-status-indicators-box { spacing: 22px; } +.just-perfection-api-panel-indicator-padding-size23 .panel-status-indicators-box { spacing: 23px; } +.just-perfection-api-panel-indicator-padding-size24 .panel-status-indicators-box { spacing: 24px; } +.just-perfection-api-panel-indicator-padding-size25 .panel-status-indicators-box { spacing: 25px; } +.just-perfection-api-panel-indicator-padding-size26 .panel-status-indicators-box { spacing: 26px; } +.just-perfection-api-panel-indicator-padding-size27 .panel-status-indicators-box { spacing: 27px; } +.just-perfection-api-panel-indicator-padding-size28 .panel-status-indicators-box { spacing: 28px; } +.just-perfection-api-panel-indicator-padding-size29 .panel-status-indicators-box { spacing: 29px; } +.just-perfection-api-panel-indicator-padding-size30 .panel-status-indicators-box { spacing: 30px; } +.just-perfection-api-panel-indicator-padding-size31 .panel-status-indicators-box { spacing: 31px; } +.just-perfection-api-panel-indicator-padding-size32 .panel-status-indicators-box { spacing: 32px; } +.just-perfection-api-panel-indicator-padding-size33 .panel-status-indicators-box { spacing: 33px; } +.just-perfection-api-panel-indicator-padding-size34 .panel-status-indicators-box { spacing: 34px; } +.just-perfection-api-panel-indicator-padding-size35 .panel-status-indicators-box { spacing: 35px; } +.just-perfection-api-panel-indicator-padding-size36 .panel-status-indicators-box { spacing: 36px; } +.just-perfection-api-panel-indicator-padding-size37 .panel-status-indicators-box { spacing: 37px; } +.just-perfection-api-panel-indicator-padding-size38 .panel-status-indicators-box { spacing: 38px; } +.just-perfection-api-panel-indicator-padding-size39 .panel-status-indicators-box { spacing: 39px; } +.just-perfection-api-panel-indicator-padding-size40 .panel-status-indicators-box { spacing: 40px; } +.just-perfection-api-panel-indicator-padding-size41 .panel-status-indicators-box { spacing: 41px; } +.just-perfection-api-panel-indicator-padding-size42 .panel-status-indicators-box { spacing: 42px; } +.just-perfection-api-panel-indicator-padding-size43 .panel-status-indicators-box { spacing: 43px; } +.just-perfection-api-panel-indicator-padding-size44 .panel-status-indicators-box { spacing: 44px; } +.just-perfection-api-panel-indicator-padding-size45 .panel-status-indicators-box { spacing: 45px; } +.just-perfection-api-panel-indicator-padding-size46 .panel-status-indicators-box { spacing: 46px; } +.just-perfection-api-panel-indicator-padding-size47 .panel-status-indicators-box { spacing: 47px; } +.just-perfection-api-panel-indicator-padding-size48 .panel-status-indicators-box { spacing: 48px; } +.just-perfection-api-panel-indicator-padding-size49 .panel-status-indicators-box { spacing: 49px; } +.just-perfection-api-panel-indicator-padding-size50 .panel-status-indicators-box { spacing: 50px; } +.just-perfection-api-panel-indicator-padding-size51 .panel-status-indicators-box { spacing: 51px; } +.just-perfection-api-panel-indicator-padding-size52 .panel-status-indicators-box { spacing: 52px; } +.just-perfection-api-panel-indicator-padding-size53 .panel-status-indicators-box { spacing: 53px; } +.just-perfection-api-panel-indicator-padding-size54 .panel-status-indicators-box { spacing: 54px; } +.just-perfection-api-panel-indicator-padding-size55 .panel-status-indicators-box { spacing: 55px; } +.just-perfection-api-panel-indicator-padding-size56 .panel-status-indicators-box { spacing: 56px; } +.just-perfection-api-panel-indicator-padding-size57 .panel-status-indicators-box { spacing: 57px; } +.just-perfection-api-panel-indicator-padding-size58 .panel-status-indicators-box { spacing: 58px; } +.just-perfection-api-panel-indicator-padding-size59 .panel-status-indicators-box { spacing: 59px; } +.just-perfection-api-panel-indicator-padding-size60 .panel-status-indicators-box { spacing: 60px; } + +.just-perfection-api-no-window-close .window-close, +.just-perfection-api-no-window-close.just-perfection .window-close +{ + height: 0; + width: 0; + background: transparent; + border-radius: 0; + border: 0; + spacing: 0; + box-shadow: none; +} + +.just-perfection-api-no-ripple-box .ripple-box +{ + background-color: transparent; +} + +/** + * This can refresh other styles that is not inculding any standard css styles. + * values are not important here. Just do something that can change the look + */ +.just-perfection-api-refresh-styles .panel-button, +.just-perfection-api-refresh-styles .panel-status-indicators-box, +.just-perfection-api-refresh-styles .panel-button StIcon, +.just-perfection-api-refresh-styles .system-status-icon +{ + background-color: gold; + color: gold; + border-radius: 100px; +} + +.just-perfection-api-no-weather .weather-button, +.just-perfection-api-no-weather .weather-button *, +.just-perfection-api-no-world-clocks .world-clocks-button, +.just-perfection-api-no-world-clocks .world-clocks-button *, +.just-perfection-api-no-events-button .events-button, +.just-perfection-api-no-events-button .events-button * +{ + padding: 0; + margin: 0; + border: 0; + height: 0; + width: 0; +} + +.just-perfection-api-panel-icon-size1 .system-status-icon, .just-perfection-api-panel-icon-size1 .panel-button StIcon { icon-size: 1px; } +.just-perfection-api-panel-icon-size2 .system-status-icon, .just-perfection-api-panel-icon-size2 .panel-button StIcon { icon-size: 2px; } +.just-perfection-api-panel-icon-size3 .system-status-icon, .just-perfection-api-panel-icon-size3 .panel-button StIcon { icon-size: 3px; } +.just-perfection-api-panel-icon-size4 .system-status-icon, .just-perfection-api-panel-icon-size4 .panel-button StIcon { icon-size: 4px; } +.just-perfection-api-panel-icon-size5 .system-status-icon, .just-perfection-api-panel-icon-size5 .panel-button StIcon { icon-size: 5px; } +.just-perfection-api-panel-icon-size6 .system-status-icon, .just-perfection-api-panel-icon-size6 .panel-button StIcon { icon-size: 6px; } +.just-perfection-api-panel-icon-size7 .system-status-icon, .just-perfection-api-panel-icon-size7 .panel-button StIcon { icon-size: 7px; } +.just-perfection-api-panel-icon-size8 .system-status-icon, .just-perfection-api-panel-icon-size8 .panel-button StIcon { icon-size: 8px; } +.just-perfection-api-panel-icon-size9 .system-status-icon, .just-perfection-api-panel-icon-size9 .panel-button StIcon { icon-size: 9px; } +.just-perfection-api-panel-icon-size10 .system-status-icon, .just-perfection-api-panel-icon-size10 .panel-button StIcon { icon-size: 10px; } +.just-perfection-api-panel-icon-size11 .system-status-icon, .just-perfection-api-panel-icon-size11 .panel-button StIcon { icon-size: 11px; } +.just-perfection-api-panel-icon-size12 .system-status-icon, .just-perfection-api-panel-icon-size12 .panel-button StIcon { icon-size: 12px; } +.just-perfection-api-panel-icon-size13 .system-status-icon, .just-perfection-api-panel-icon-size13 .panel-button StIcon { icon-size: 13px; } +.just-perfection-api-panel-icon-size14 .system-status-icon, .just-perfection-api-panel-icon-size14 .panel-button StIcon { icon-size: 14px; } +.just-perfection-api-panel-icon-size15 .system-status-icon, .just-perfection-api-panel-icon-size15 .panel-button StIcon { icon-size: 15px; } +.just-perfection-api-panel-icon-size16 .system-status-icon, .just-perfection-api-panel-icon-size16 .panel-button StIcon { icon-size: 16px; } +.just-perfection-api-panel-icon-size17 .system-status-icon, .just-perfection-api-panel-icon-size17 .panel-button StIcon { icon-size: 17px; } +.just-perfection-api-panel-icon-size18 .system-status-icon, .just-perfection-api-panel-icon-size18 .panel-button StIcon { icon-size: 18px; } +.just-perfection-api-panel-icon-size19 .system-status-icon, .just-perfection-api-panel-icon-size19 .panel-button StIcon { icon-size: 19px; } +.just-perfection-api-panel-icon-size20 .system-status-icon, .just-perfection-api-panel-icon-size20 .panel-button StIcon { icon-size: 20px; } +.just-perfection-api-panel-icon-size21 .system-status-icon, .just-perfection-api-panel-icon-size21 .panel-button StIcon { icon-size: 21px; } +.just-perfection-api-panel-icon-size22 .system-status-icon, .just-perfection-api-panel-icon-size22 .panel-button StIcon { icon-size: 22px; } +.just-perfection-api-panel-icon-size23 .system-status-icon, .just-perfection-api-panel-icon-size23 .panel-button StIcon { icon-size: 23px; } +.just-perfection-api-panel-icon-size24 .system-status-icon, .just-perfection-api-panel-icon-size24 .panel-button StIcon { icon-size: 24px; } +.just-perfection-api-panel-icon-size25 .system-status-icon, .just-perfection-api-panel-icon-size25 .panel-button StIcon { icon-size: 25px; } +.just-perfection-api-panel-icon-size26 .system-status-icon, .just-perfection-api-panel-icon-size26 .panel-button StIcon { icon-size: 26px; } +.just-perfection-api-panel-icon-size27 .system-status-icon, .just-perfection-api-panel-icon-size27 .panel-button StIcon { icon-size: 27px; } +.just-perfection-api-panel-icon-size28 .system-status-icon, .just-perfection-api-panel-icon-size28 .panel-button StIcon { icon-size: 28px; } +.just-perfection-api-panel-icon-size29 .system-status-icon, .just-perfection-api-panel-icon-size29 .panel-button StIcon { icon-size: 29px; } +.just-perfection-api-panel-icon-size30 .system-status-icon, .just-perfection-api-panel-icon-size30 .panel-button StIcon { icon-size: 30px; } +.just-perfection-api-panel-icon-size31 .system-status-icon, .just-perfection-api-panel-icon-size31 .panel-button StIcon { icon-size: 31px; } +.just-perfection-api-panel-icon-size32 .system-status-icon, .just-perfection-api-panel-icon-size32 .panel-button StIcon { icon-size: 32px; } +.just-perfection-api-panel-icon-size33 .system-status-icon, .just-perfection-api-panel-icon-size33 .panel-button StIcon { icon-size: 33px; } +.just-perfection-api-panel-icon-size34 .system-status-icon, .just-perfection-api-panel-icon-size34 .panel-button StIcon { icon-size: 34px; } +.just-perfection-api-panel-icon-size35 .system-status-icon, .just-perfection-api-panel-icon-size35 .panel-button StIcon { icon-size: 35px; } +.just-perfection-api-panel-icon-size36 .system-status-icon, .just-perfection-api-panel-icon-size36 .panel-button StIcon { icon-size: 36px; } +.just-perfection-api-panel-icon-size37 .system-status-icon, .just-perfection-api-panel-icon-size37 .panel-button StIcon { icon-size: 37px; } +.just-perfection-api-panel-icon-size38 .system-status-icon, .just-perfection-api-panel-icon-size38 .panel-button StIcon { icon-size: 38px; } +.just-perfection-api-panel-icon-size39 .system-status-icon, .just-perfection-api-panel-icon-size39 .panel-button StIcon { icon-size: 39px; } +.just-perfection-api-panel-icon-size40 .system-status-icon, .just-perfection-api-panel-icon-size40 .panel-button StIcon { icon-size: 40px; } +.just-perfection-api-panel-icon-size41 .system-status-icon, .just-perfection-api-panel-icon-size41 .panel-button StIcon { icon-size: 41px; } +.just-perfection-api-panel-icon-size42 .system-status-icon, .just-perfection-api-panel-icon-size42 .panel-button StIcon { icon-size: 42px; } +.just-perfection-api-panel-icon-size43 .system-status-icon, .just-perfection-api-panel-icon-size43 .panel-button StIcon { icon-size: 43px; } +.just-perfection-api-panel-icon-size44 .system-status-icon, .just-perfection-api-panel-icon-size44 .panel-button StIcon { icon-size: 44px; } +.just-perfection-api-panel-icon-size45 .system-status-icon, .just-perfection-api-panel-icon-size45 .panel-button StIcon { icon-size: 45px; } +.just-perfection-api-panel-icon-size46 .system-status-icon, .just-perfection-api-panel-icon-size46 .panel-button StIcon { icon-size: 46px; } +.just-perfection-api-panel-icon-size47 .system-status-icon, .just-perfection-api-panel-icon-size47 .panel-button StIcon { icon-size: 47px; } +.just-perfection-api-panel-icon-size48 .system-status-icon, .just-perfection-api-panel-icon-size48 .panel-button StIcon { icon-size: 48px; } +.just-perfection-api-panel-icon-size49 .system-status-icon, .just-perfection-api-panel-icon-size49 .panel-button StIcon { icon-size: 49px; } +.just-perfection-api-panel-icon-size50 .system-status-icon, .just-perfection-api-panel-icon-size50 .panel-button StIcon { icon-size: 50px; } +.just-perfection-api-panel-icon-size51 .system-status-icon, .just-perfection-api-panel-icon-size51 .panel-button StIcon { icon-size: 51px; } +.just-perfection-api-panel-icon-size52 .system-status-icon, .just-perfection-api-panel-icon-size52 .panel-button StIcon { icon-size: 52px; } +.just-perfection-api-panel-icon-size53 .system-status-icon, .just-perfection-api-panel-icon-size53 .panel-button StIcon { icon-size: 53px; } +.just-perfection-api-panel-icon-size54 .system-status-icon, .just-perfection-api-panel-icon-size54 .panel-button StIcon { icon-size: 54px; } +.just-perfection-api-panel-icon-size55 .system-status-icon, .just-perfection-api-panel-icon-size55 .panel-button StIcon { icon-size: 55px; } +.just-perfection-api-panel-icon-size56 .system-status-icon, .just-perfection-api-panel-icon-size56 .panel-button StIcon { icon-size: 56px; } +.just-perfection-api-panel-icon-size57 .system-status-icon, .just-perfection-api-panel-icon-size57 .panel-button StIcon { icon-size: 57px; } +.just-perfection-api-panel-icon-size58 .system-status-icon, .just-perfection-api-panel-icon-size58 .panel-button StIcon { icon-size: 58px; } +.just-perfection-api-panel-icon-size59 .system-status-icon, .just-perfection-api-panel-icon-size59 .panel-button StIcon { icon-size: 59px; } +.just-perfection-api-panel-icon-size60 .system-status-icon, .just-perfection-api-panel-icon-size60 .panel-button StIcon { icon-size: 60px; } + + +.just-perfection-api-osd-position-top .osd-window { margin: 4em 2.5em; } +.just-perfection-api-osd-position-center .osd-window { margin: 4em 3.5em; } +.just-perfection-api-osd-position-bottom .osd-window { margin: 4em 3em; } + +.just-perfection-api-no-dash-separator .dash-separator, +.just-perfection-api-no-app-menu-label .panel-status-menu-box StLabel +{ + width: 0; + height: 0; + spacing: 0; + padding: 0; + margin: 0; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui new file mode 100644 index 0000000..37b57ff --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui @@ -0,0 +1,123 @@ + + + + + behavior + Behavior + applications-engineering-symbolic + + + + Behavior + + + + Hot Corner + hot_corner_switch + + + center + + + + + + + + App Gesture + + gesture_switch + + + center + + + + + + + + Workspace Wraparound + Next workspace will be the first workspace when you are in the last workspace. and previous workspace will be the last workspace when you are in the first workspace. + workspace_wrap_around_switch + + + center + + + + + + + + Window Demands Attention Focus + Removes window is ready notification and focus on the window + window_demands_attention_focus_switch + + + center + + + + + + + + Type to Search + You can start search without search entry or even focusing on it in overview + type_to_search_switch + + + center + + + + + + + + Always Show Workspace Switcher + Shows workspace switcher even when only one workspace used with dynamic workspaces + workspace_switcher_should_show_switch + + + center + + + + + + + + Double Super to App Grid + Shows app grid when you double hit super key fast + double_super_to_appgrid_switch + + + center + + + + + + + + Startup Status + When GNOME Shell is starting up for the first time + startup_status_model + + + + + + + + + + + Desktop + Overview + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui new file mode 100644 index 0000000..527094d --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui @@ -0,0 +1,732 @@ + + + + + customize + Customize + applications-utilities-symbolic + + + + Customize + + + + Workspace Background Corner Size + Workspace background corner size in overview + workspace_background_corner_size_model + + + + + + Panel Size + panel_size_model + + + + + + Panel Icon Size + panel_icon_size_model + + + + + + Panel Button Padding Size + panel_button_padding_size_model + + + + + + Panel Indicator Padding Size + panel_indicator_padding_size_model + + + + + + Panel Corner Size + panel_corner_size_model + + + + + + Panel Position + top_panel_position_model + + + + + + Clock Menu Position + clock_menu_position_model + + + + + + Clock Menu Position Offset + clock_menu_position_offset_model + + + + + + Workspace Switcher Size + workspace_switcher_size_model + + + + + + Animation + animation_model + + + + + + Dash Icon Size + dash_icon_size_model + + + + + + Notification Banner Position + Notification popup position when notifications show up on the screen + notification_banner_position_model + + + + + + OSD Position + OSD position when on screen display shows up on the screen + osd_position_model + + + + + + Alt Tab Window Preview Size + alt_tab_window_preview_size_model + + + + + + Alt Tab Window Preview Icon Size + alt_tab_small_icon_size_model + + + + + + Alt Tab Icon Size + alt_tab_icon_size_model + + + + + + Looking Glass Width + looking_glass_width_model + + + + + + Looking Glass Height + looking_glass_height_model + + + + + + + + + + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + By Shell Theme + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + By Shell Theme + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + By Shell Theme + No Corner + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + + + + + + Top + Bottom + + + + + + Center + Right + Left + + + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + + + + Default + 1% + 2% + 3% + 4% + 5% + 6% + 7% + 8% + 9% + 10% + 11% + 12% + 13% + 14% + 15% + 16% + 17% + 18% + 19% + 20% + 21% + 22% + 23% + 24% + 25% + 26% + 27% + 28% + 29% + 30% + + + + + + No Animation + Default Speed + Fastest + Faster + Fast + Slow + Slower + Slowest + + + + + + Default + 32px + 48px + 64px + + + + + + Top Start + Top Center + Top End + Bottom Start + Bottom Center + Bottom End + + + + + + Default + Top Start + Top Center + Top End + Bottom Start + Bottom Center + Bottom End + Center Start + Center + Center End + + + + + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + Default + 10% + 20% + 30% + 40% + 50% + 60% + 70% + 80% + 90% + + + + + + Default + 10% + 20% + 30% + 40% + 50% + 60% + 70% + 80% + 90% + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui new file mode 100644 index 0000000..6f3d02a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui @@ -0,0 +1,169 @@ + + + + + icons + Icons + emblem-photos-symbolic + + + + Icons + + + + App Menu Icon + app_menu_icon_switch + + + center + + + + + + + + Panel Notification Icon + panel_notification_icon_switch + + + center + + + + + + + + Power Icon + power_icon_switch + + + center + + + + + + + + Panel Arrow + panel_arrow_switch + + + center + + + + + + + + Window Picker Icon + The icon under window preview in overview + window_picker_icon_switch + + + center + + + + + + + + Activities Button Icon + The icon under window preview in overview + activities_button_icon_path_button + + + True + False + horizontal + + + + False + True + True + True + + + + True + False + edit-delete-symbolic + 1 + + + + + + + + + True + True + True + True + + + + True + False + document-open-symbolic + 1 + + + + + + + + + False + False + + + + + + + + + + + + + Activities Button Icon in Monochrome + activities_button_icon_monochrome_switch + + + center + + + + + + + + Activities Button Icon With Label + Only works when you have selected an icon for activities button + activities_button_label_switch + + + center + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui new file mode 100644 index 0000000..13841cb --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui @@ -0,0 +1,161 @@ + + + + + + + + application/xml + image/png + image/jpeg + + + + + + + Select File + 0 + open + 1 + file_chooser_image_filter + + + + profile + Profile + view-list-symbolic + + + + Profile + + + + True + False + center + You can choose between pre-defined profiles or you can simply use your own customized settings + 0 + True + 0 + 12 + 12 + + + + + + + + + + True + True + 0 + 0 + + + True + True + Default + 1 + 1 + 1 + + + + + True + True + Custom + profile_default + 1 + 1 + + + + + True + True + Minimal + profile_default + 1 + 1 + + + + + True + True + Super Minimal + profile_default + 1 + 1 + + + + + + + + + + + + Override + + + + Shell Theme + Overrides the shell theme partially to create a minimal desktop + theme_switch + + + center + + + + + + + + + + + Links + + + + Bug Report + bug_report_linkbutton + + + https://gitlab.gnome.org/jrahmatzadeh/just-perfection/-/issues + + + + + + + + Support via Patreon + patreon_linkbutton + + + https://www.patreon.com/justperfection + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui new file mode 100644 index 0000000..80c589f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui @@ -0,0 +1,368 @@ + + + + + visibility + Visibility + weather-clear-symbolic + + + + Visibility + + + + Panel + panel_switch + + + center + + + + + + + + Panel in Overview + panel_in_overview_switch + + + + center + + + + + + + + Activities Button + Button in panel to toggle overview visibility + activities_button_switch + + + center + + + + + + + + App Menu + The menu button in panel with focused window text + app_menu_switch + + + center + + + + + + + + App Menu Label + The text label in app menu button + app_menu_label_switch + + + center + + + + + + + + Clock Menu + Also known as date menu shows date and time in panel + clock_menu_switch + + + center + + + + + + + + Keyboard Layout + Keyboard Layout indicator button in panel + keyboard_layout_switch + + + center + + + + + + + + Accessibility Menu + Accessibility Menu indicator button in panel + accessibility_menu_switch + + + center + + + + + + + + System Menu (Aggregate Menu) + System menu holds power, volume and network icons in panel + aggregate_menu_switch + + + center + + + + + + + + Quick Settings + Quick settings menu in panel + quick_settings_switch + + + center + + + + + + + + World Clock + World clock in clock menu + world_clock_switch + + + center + + + + + + + + Weather + Weather in clock menu + weather_switch + + + center + + + + + + + + Calendar + Calendar in clock menu + calendar_switch + + + center + + + + + + + + Events + Events button in clock menu + events_button_switch + + + center + + + + + + + + Search + Search entry in overview + search_switch + + + center + + + + + + + + Dash + Dash holds favorite and opened applications icons + dash_switch + + + center + + + + + + + + Dash Separator + Dash separator line that separates pin apps from unpin apps + dash_separator_switch + + + center + + + + + + + + Show Applications Button + Button in dash that toggles applications list visibility + show_apps_button_switch + + + center + + + + + + + + On Screen Display (OSD) + Volume and brightness on screen display when the change happens + osd_switch + + + center + + + + + + + + Workspace Popup + Popup that appears on the screen when you change the workspace + workspace_popup_switch + + + center + + + + + + + + Workspace Switcher + Also refers to workspace thumbnails that you see in overview for selecting a workspace + workspace_switch + + + center + + + + + + + + Workspaces App Grid + Workspace boxes in app grid + workspaces_in_app_grid_switch + + + center + + + + + + + + Window Picker Close Button + The close button on window preview in overview + window_preview_close_button_switch + + + center + + + + + + + + Window Picker Caption + The text under window preview in overview + window_preview_caption_switch + + + center + + + + + + + + Background Menu + When you right click on desktop background + background_menu_switch + + + center + + + + + + + + Ripple Box + Hot corner animation effects + ripple_box_switch + + + center + + + + + + + + Take Screenshot button in Window Menu + Take screenshot button in title bar right click menu + window_menu_take_screenshot_button_switch + + + center + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/behavior.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/behavior.ui new file mode 100644 index 0000000..ba51130 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/behavior.ui @@ -0,0 +1,616 @@ + + + + + True + True + vertical + + + + True + False + 12 + + + + True + False + Behavior + + + + + + + + + + + + True + False + 0 + 36 + + + + True + False + none + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Hot Corner + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + App Gesture + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Workspace Wraparound + 0 + 1 + + + + + + True + False + center + Next workspace will be the first workspace when you are in the last workspace. and previous workspace will be the last workspace when you are in the first workspace. + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Window Demands Attention Focus + 0 + 1 + + + + + + True + False + center + Removes window is ready notification and focus on the window + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Type to Search + 0 + 1 + + + + + + True + False + center + You can start search without search entry or even focusing on it in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Always Show Workspace Switcher + 0 + 1 + + + + + + True + False + center + Shows workspace switcher even when only one workspace used with dynamic workspaces + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Double Super to App Grid + 0 + 1 + + + + + + True + False + center + Shows app grid when you double hit super key fast + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Startup Status + 0 + 1 + + + + + + True + False + center + When GNOME Shell is starting up for the first time + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + Desktop + Overview + + + + + + + + + + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/customize.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/customize.ui new file mode 100644 index 0000000..116c6a6 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/customize.ui @@ -0,0 +1,1586 @@ + + + + + True + True + vertical + + + + True + False + 12 + + + + True + False + Customize + + + + + + + + + + + + True + False + 0 + + + + True + False + none + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Workspace Background Corner Size + 0 + 1 + + + + + + True + False + center + Workspace background corner size in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Size + 0 + 1 + + + + + + True + True + center + + By Shell Theme + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Icon Size + 0 + 1 + + + + + + True + True + center + + By Shell Theme + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Button Padding Size + 0 + 1 + + + + + + True + True + center + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Indicator Padding Size + 0 + 1 + + + + + + True + True + center + + By Shell Theme + 0px + 1px + 2px + 3px + 4px + 5px + 6px + 7px + 8px + 9px + 10px + 11px + 12px + 13px + 14px + 15px + 16px + 17px + 18px + 19px + 20px + 21px + 22px + 23px + 24px + 25px + 26px + 27px + 28px + 29px + 30px + 31px + 32px + 33px + 34px + 35px + 36px + 37px + 38px + 39px + 40px + 41px + 42px + 43px + 44px + 45px + 46px + 47px + 48px + 49px + 50px + 51px + 52px + 53px + 54px + 55px + 56px + 57px + 58px + 59px + 60px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Corner Size + 0 + 1 + + + + + + True + True + center + + By Shell Theme + No Corner + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Position + 0 + 1 + + + + + + True + True + center + + Top + Bottom + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Clock Menu Position + 0 + 1 + + + + + + True + True + center + + Center + Right + Left + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Clock Menu Position Offset + 0 + 1 + + + + + + True + True + center + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Workspace Switcher Size + 0 + 1 + + + + + + True + True + center + + Default + 1% + 2% + 3% + 4% + 5% + 6% + 7% + 8% + 9% + 10% + 11% + 12% + 13% + 14% + 15% + 16% + 17% + 18% + 19% + 20% + 21% + 22% + 23% + 24% + 25% + 26% + 27% + 28% + 29% + 30% + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Animation + 0 + 1 + + + + + + True + True + center + + No Animation + Default Speed + Fastest + Faster + Fast + Slow + Slower + Slowest + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Dash Icon Size + 0 + 1 + + + + + + True + True + center + + Default + 32px + 48px + 64px + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Notification Banner Position + 0 + 1 + + + + + + True + False + center + Notification popup position when notifications show up on the screen + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + Top Start + Top Center + Top End + Bottom Start + Bottom Center + Bottom End + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + OSD Position + 0 + 1 + + + + + + True + False + center + OSD position when on screen display shows up on the screen + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + Default + Top Start + Top Center + Top End + Bottom Start + Bottom Center + Bottom End + Center Start + Center + Center End + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Alt Tab Window Preview Size + 0 + 1 + + + + + + True + True + center + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Alt Tab Window Preview Icon Size + 0 + 1 + + + + + + True + True + center + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Alt Tab Icon Size + 0 + 1 + + + + + + True + True + center + + Default + 32 + 64 + 128 + 256 + 512 + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Looking Glass Width + 0 + 1 + + + + + + True + True + center + + Default + 10% + 20% + 30% + 40% + 50% + 60% + 70% + 80% + 90% + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Looking Glass Height + 0 + 1 + + + + + + True + True + center + + Default + 10% + 20% + 30% + 40% + 50% + 60% + 70% + 80% + 90% + + + + + + + + + + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/icons.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/icons.ui new file mode 100644 index 0000000..a04053e --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/icons.ui @@ -0,0 +1,550 @@ + + + + + True + True + vertical + + + + True + False + 12 + + + + True + False + Icons + + + + + + + + + + + + True + False + 0 + 36 + + + + True + False + none + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + App Menu Icon + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Notification Icon + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Power Icon + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel Arrow + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Window Picker Icon + 0 + 1 + + + + + + True + False + center + The icon under window preview in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Activities Button Icon + 0 + 1 + + + + + + True + False + horizontal + + + + False + True + True + True + + + + True + False + edit-delete-symbolic + 1 + + + + + + + + + True + True + True + True + + + + True + False + document-open-symbolic + 1 + + + + + + + + + False + False + + + + + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Activities Button Icon in Monochrome + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Activities Button Icon With Label + 0 + 1 + + + + + + True + False + center + Only works when you have selected an icon for activities button + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/intro.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/intro.ui new file mode 100644 index 0000000..ef60340 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/intro.ui @@ -0,0 +1,35 @@ + + + + + True + False + 36 + center + center + + + + True + True + start + start + 0 + 0 + https://www.patreon.com/justperfection + + + + True + False + center + vertical + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/main.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/main.ui new file mode 100644 index 0000000..ea81568 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/main.ui @@ -0,0 +1,176 @@ + + + + + + + +
+ + Bug Report + prefs.show-bug-report + + + Support via Patreon + prefs.show-patreon + +
+
+ + + + + True + True + 1 + + + + True + True + True + + + + True + False + system-search-symbolic + 1 + + + + + + + + + + True + True + True + True + primary_menu + + + + True + False + open-menu-symbolic + 1 + + + + + + + + + + application/xml + image/png + image/jpeg + + + + + + + Select File + 0 + open + 1 + file_chooser_image_filter + + + + + + True + True + vertical + 1 + + + + + + True + True + + + + True + True + slide-up + True + 24 + 24 + 5 + 5 + 1 + 250 + + + + True + True + vertical + 1 + + + + True + True + 1 + + + + + + + + + + + + + + + + + 450 + 450 + never + True + True + 1 + + + + True + False + + + + True + False + 36 + 36 + 36 + 36 + vertical + + + + + + + + + + + + + + +
diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/no-results-found.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/no-results-found.ui new file mode 100644 index 0000000..04571d8 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/no-results-found.ui @@ -0,0 +1,35 @@ + + + + + False + False + 0 + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + center + center + No Matches + 1 + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/override.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/override.ui new file mode 100644 index 0000000..d58bfcf --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/override.ui @@ -0,0 +1,131 @@ + + + + + True + True + vertical + + + + True + False + 12 + + + + True + False + Override + + + + + + + + + + + + True + False + 0 + 36 + + + + True + False + none + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + 1 + 1 + vertical + + + + True + False + center + Shell Theme + 0 + 1 + + + + + + True + False + center + Overrides the shell theme partially to create a minimal desktop + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/profile.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/profile.ui new file mode 100644 index 0000000..0eb06dc --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/profile.ui @@ -0,0 +1,104 @@ + + + + + True + True + vertical + 36 + + + + True + False + 12 + vertical + + + + True + False + Profile + 0 + + + + + + + + + True + False + center + You can choose between pre-defined profiles or you can simply use your own customized settings + 0 + True + 0 + 12 + 12 + + + + + + + + + + True + True + + + True + True + Default + 1 + 1 + 1 + + + + + True + True + Custom + profile_default + 1 + 1 + + + + + True + True + Minimal + profile_default + 1 + 1 + + + + + True + True + Super Minimal + profile_default + 1 + 1 + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/visibility.ui b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/visibility.ui new file mode 100644 index 0000000..ccc89ba --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/just-perfection-desktop@just-perfection/ui/visibility.ui @@ -0,0 +1,2078 @@ + + + + + True + True + vertical + + + + True + False + 12 + + + + True + False + Visibility + + + + + + + + + + + + True + False + 0 + 36 + + + + True + False + none + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + False + center + Panel in Overview + 0 + 1 + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + + True + True + vertical + + + + True + False + center + Activities Button + 0 + 1 + + + + + + True + False + center + Button in panel to toggle overview visibility + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + App Menu + 0 + 1 + + + + + + True + False + center + The menu button in panel with focused window text + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + App Menu Label + 0 + 1 + + + + + + True + False + center + The text label in app menu button + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Clock Menu + 0 + 1 + + + + + + True + False + center + Also known as date menu shows date and time in panel + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Keyboard Layout + 0 + 1 + + + + + + True + False + center + Keyboard Layout indicator button in panel + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Accessibility Menu + 0 + 1 + + + + + + True + False + center + Accessibility Menu indicator button in panel + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + System Menu (Aggregate Menu) + 0 + 1 + + + + + + True + False + center + System menu holds power, volume and network icons in panel + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Quick Settings + 0 + 1 + + + + + + True + False + center + Quick settings menu in panel + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + World Clock + 0 + 1 + + + + + + True + False + center + World clock in clock menu + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Weather + 0 + 1 + + + + + + True + False + center + Weather in clock menu + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Calendar + 0 + 1 + + + + + + True + False + center + Calendar in clock menu + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Events + 0 + 1 + + + + + + True + False + center + Events button in clock menu + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Search + 0 + 1 + + + + + + True + False + center + Search entry in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Dash + 0 + 1 + + + + + + True + False + center + Dash holds favorite and opened applications icons + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Dash Separator + 0 + 1 + + + + + + True + False + center + Dash separator line that separates pin apps from unpin apps + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Show Applications Button + 0 + 1 + + + + + + True + False + center + Button in dash that toggles applications list visibility + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + On Screen Display (OSD) + 0 + 1 + + + + + + True + False + center + Volume and brightness on screen display when the change happens + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Workspace Popup + 0 + 1 + + + + + + True + False + center + Popup that appears on the screen when you change the workspace + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Workspace Switcher + 0 + 1 + + + + + + True + False + center + Also refers to workspace thumbnails that you see in overview for selecting a workspace + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Workspaces App Grid + 0 + 1 + + + + + + True + False + center + Workspace boxes in app grid + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Window Picker Close Button + 0 + 1 + + + + + + True + False + center + The close button on window preview in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Window Picker Caption + 0 + 1 + + + + + + True + False + center + The text under window preview in overview + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Background Menu + 0 + 1 + + + + + + True + False + center + When you right click on desktop background + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Ripple Box + 0 + 1 + + + + + + True + False + center + Hot corner animation effects + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + True + True + + + + True + False + 12 + 12 + 12 + 12 + vertical + + + + True + False + 32 + + + + True + True + vertical + + + + True + False + center + Take Screenshot button in Window Menu + 0 + 1 + + + + + + True + False + center + Take screenshot button in title bar right click menu + 0 + True + 0 + 12 + + + + + + + + + + + + + True + True + center + + + + + + + + + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/extension.js new file mode 100644 index 0000000..645c360 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/extension.js @@ -0,0 +1,435 @@ +/* extension.js + * + * 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 + */ + +/* exported init */ + +'use strict'; + +const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi; + +const Main = imports.ui.main; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const SystemActions = imports.misc.systemActions; +const ExtensionUtils = imports.misc.extensionUtils; +const System = Main.panel.statusArea.aggregateMenu._system; +const SystemMenu = System.menu; + +const GnomeSession = imports.misc.gnomeSession; +let SessionManager = null; + +const Config = imports.misc.config; +const SHELL_MAJOR_VERSION = parseInt(Config.PACKAGE_VERSION.split('.')[0]); + +let DefaultActions; +let bindFlags; +let item; +let button; + +var LabelLauncher = new GObject.registerClass( +class LabelLauncher extends St.Widget { +_init() { + this._labelText = ""; + this.label = new St.Label({ style_class: 'dash-label' }); + this.label.hide(); + Main.layoutManager.addChrome(this.label); + this.label_actor = this.label; + } + +showLabel(button) { + this.label.set_text(button.get_accessible_name()); + this.label.opacity = 0; + this.label.show(); + + let node = this.label.get_theme_node(); + let stageX; + let stageY; + let yOffset; + + if(SHELL_MAJOR_VERSION == 3) { + stageX = Math.floor(button.get_transformed_position().slice()[0] + (button.get_width()/2)); + stageY = Math.floor(Main.panel.statusArea.aggregateMenu.menu.box.get_transformed_position().slice()[1] + Main.panel.statusArea.aggregateMenu.menu.box.get_height()); + yOffset = node.get_length('-x-offset'); + } else if(SHELL_MAJOR_VERSION >= 40) { + stageX = button.get_transformed_extents().get_center().x; + stageY = Main.panel.statusArea.aggregateMenu.menu.box.get_transformed_extents().get_bottom_right().y; + yOffset = node.get_length('-y-offset'); + } + + const labelWidth = this.label.get_width(); + const xOffset = Math.floor(labelWidth / 2); + + const x = stageX - xOffset; + const y = stageY + yOffset; + + this.label.set_position(x, y); + this.label.ease({ + opacity: 255, + duration: 100, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + }); + } + +hideLabel() { + this.label.ease({ + opacity: 0, + duration: 100, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => this.label.hide(), + }); + } +}); + +var _systemMenuButtons = new GObject.registerClass( +class SystemMenuButtons extends PanelMenu.SystemIndicator { + +_init() { + + this._showLabelTimeoutId = 0; + this._resetHoverTimeoutId = 0; + this._labelShowing = false; + + DefaultActions = new SystemActions.getDefault(); + this._settings = ExtensionUtils.getSettings(); + + SystemMenu.actor.remove_child(System._orientationLockItem); + SystemMenu.actor.remove_child(System._settingsItem); + SystemMenu.actor.remove_child(System._lockScreenItem); + SystemMenu.actor.remove_child(System._sessionSubMenu); + + this._createMenu(); + + this._connectSettings(); + + SystemMenu.connect('open-state-changed', (menu, open) => { + if(!open) + return; + DefaultActions._updateOrientationLock(); + DefaultActions._sessionUpdated(); + DefaultActions.forceUpdate(); + }); + } + +_syncLabel(tooltip, button) { + if (tooltip.child.hover) { + if (this._showLabelTimeoutId == 0) { + let timeout = this._labelShowing ? 0 : 100; + this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, + () => { + this._labelShowing = true; + tooltip.showLabel(button); + this._showLabelTimeoutId = 0; + return GLib.SOURCE_REMOVE; + }); + GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] tooltip.showLabel'); + if (this._resetHoverTimeoutId > 0) { + GLib.source_remove(this._resetHoverTimeoutId); + this._resetHoverTimeoutId = 0; + } + } + } else { + if (this._showLabelTimeoutId > 0) + GLib.source_remove(this._showLabelTimeoutId); + this._showLabelTimeoutId = 0; + tooltip.hideLabel(); + if (this._labelShowing) { + this._resetHoverTimeoutId = GLib.timeout_add( + GLib.PRIORITY_DEFAULT, 100, + () => { + this._labelShowing = false; + this._resetHoverTimeoutId = 0; + return GLib.SOURCE_REMOVE; + }); + GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing'); + } + } + } + +_hookUpLabel(tooltip, button) { + tooltip.child.connect('notify::hover', () => { + this._syncLabel(tooltip, button); + }); + + tooltip.child.connect('clicked', () => { + this._labelShowing = false; + tooltip.hideLabel(); + }); + } + +_createActionButton(iconName, accessibleName) { + + let roundButton = new St.Button({ reactive: true, + can_focus: true, + track_hover: true, + accessible_name: accessibleName, + x_expand: true, + x_align: 2, + style_class: 'rounded-menu-buttons', + }); + + roundButton.child = new St.Icon({ icon_name: iconName, icon_size: this._settings.get_int('icon-size') }); + + let useCustomColor = this._settings.get_boolean('use-custom-color'); + roundButton.set_style("color: " + `${useCustomColor ? this._settings.get_string('color') : '#eeeeec'};` + + " padding: " + this._settings.get_int('padding') + "px; " + + "border-radius: " + this._settings.get_int('border-radius') + "px;"); + + + let tooltip = new LabelLauncher(); + tooltip.child = roundButton; + this._hookUpLabel(tooltip, roundButton); + + return roundButton; + } + +_createMenu() { + bindFlags = GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE; + item = new PopupMenu.PopupBaseMenuItem({ reactive: false, can_focus: false }); + let iconSize = this._settings.get_int('icon-size'); + let boolean; + + // ORIENTATION BUTTON + + this._orientationButton = this._createActionButton(DefaultActions.orientation_lock_icon, DefaultActions.getName(_('lock-orientation'))); + this._orientationButton.connect('clicked', () => { + DefaultActions.activateLockOrientation(); + }); + + item.actor.add(this._orientationButton); + DefaultActions.bind_property('can-lock-orientation', this._orientationButton, 'visible', bindFlags); + + DefaultActions.connect('notify::orientation-lock-icon', () => { + let iconName = DefaultActions.orientation_lock_icon; + let labelText = DefaultActions.getName('lock-orientation'); + + this._orientationButton.setIcon(iconName); + this._orientationButton.label.text = labelText; }); + + // SETTINGS BUTTON + + let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app('org.gnome.Settings.desktop') ? + Shell.AppSystem.get_default().lookup_app('org.gnome.Settings.desktop') : + Shell.AppSystem.get_default().lookup_app('gnome-control-center.desktop') + if (app) { + this._settingsButton = this._createActionButton('org.gnome.Settings-symbolic', _('Settings')); + this._settingsButton.connect('clicked', () => { + Main.overview.hide(); + this._settingsApp.activate(); + }); + + item.actor.add(this._settingsButton); + } else { + log('Missing required core component Settings, expect trouble…'); + this._settingsButton = null; + } + + // LOCK BUTTON + + this._lockButton = this._createActionButton('changes-prevent-symbolic', _('Lock')); + this._lockButton.connect('clicked', () => { + DefaultActions.activateLockScreen(); + }); + + item.actor.add(this._lockButton); + DefaultActions.bind_property('can-lock-screen', this._lockButton, 'visible', bindFlags); + + // SUSPEND + + this._suspendButton = this._createActionButton('media-playback-pause-symbolic', _('Suspend')); + this._suspendButton.connect('clicked', () => { + DefaultActions.activateSuspend(); + }); + + boolean = this._settings.get_boolean('remove-suspend-button'); + + if(boolean) { + this._suspendButton = null; + } else { + item.actor.add(this._suspendButton); + DefaultActions.bind_property('can-suspend', this._suspendButton, 'visible', bindFlags); } + + // SWITCH USER + + this._switchUserButton = this._createActionButton('system-switch-user-symbolic', _('Switch User…')); + this._switchUserButton.connect('clicked', () => { + DefaultActions.activateSwitchUser(); + }); + + item.actor.add(this._switchUserButton); + DefaultActions.bind_property('can-switch-user', this._switchUserButton, 'visible', bindFlags); + + // LOGOUT + + this._logoutButton = this._createActionButton('system-log-out-symbolic', _('Log Out')); + this._logoutButton.connect('clicked', () => { + DefaultActions.activateLogout(); + }); + + boolean = this._settings.get_boolean('remove-logout-button'); + + if(boolean) { + this._logoutButton = null; + } else { + item.actor.add(this._logoutButton) + DefaultActions.bind_property('can-logout', this._logoutButton, 'visible', bindFlags); } + + // RESTART + + this._restartButton = this._createActionButton('system-reboot-symbolic', _('Restart…')); + this._restartButton.connect('clicked', () => { + SHELL_MAJOR_VERSION >= 40 ? DefaultActions.activateRestart() : SessionManager.RebootRemote(); + }); + + boolean = this._settings.get_boolean('remove-restart-button'); + + if(boolean) { + this._restartButton = null; + } else { + item.actor.add(this._restartButton) + SHELL_MAJOR_VERSION >=40 ? DefaultActions.bind_property('can-restart', this._restartButton, 'visible', bindFlags) : + DefaultActions.bind_property('can-power-off', this._restartButton, 'visible', bindFlags) } + + // POWEROFF + + this._powerButton = this._createActionButton('system-shutdown-symbolic', _('Power Off…')); + this._powerButton.connect('clicked', () => { + DefaultActions.activatePowerOff(); + }); + + boolean = this._settings.get_boolean('remove-poweroff-button'); + + if(boolean) { + this._powerButton = null; + } else { + item.actor.add(this._powerButton) + DefaultActions.bind_property('can-power-off', this._powerButton, 'visible', bindFlags); } + + // Main Course + + SystemMenu.box.add_actor(item); + + this._getAvailableButtons(); + + DefaultActions._updateOrientationLock(); + DefaultActions._sessionUpdated(); + DefaultActions.forceUpdate(); + } + +_getAvailableButtons() { + let BUTTONS_ORDER = this._settings.get_value('buttons-order').deepUnpack(); + + const initialArray = [ + this._orientationButton, + this._settingsButton, + this._lockButton, + this._suspendButton, + this._switchUserButton, + this._logoutButton, + this._restartButton, + this._powerButton + ] + + const orderedArray = BUTTONS_ORDER.map((idx) => initialArray[idx - 1]); + + const filterdArray = orderedArray.filter(obj => obj != null); + + for (let i = 0; i < filterdArray.length; i++) { + item.remove_actor(filterdArray[i]); + item.actor.add(filterdArray[i]); + } +} + +_connectSettings() { + this.colorChanged = this._settings.connect('changed::color', this._settingsChanged.bind(this)); + this.useCustomColorChanged = this._settings.connect('changed::use-custom-color', this._settingsChanged.bind(this)); + this.removeSuspendButtonChanged = this._settings.connect('changed::remove-suspend-button', this._settingsChanged.bind(this)); + this.removeLogoutButtonChanged = this._settings.connect('changed::remove-logout-button', this._settingsChanged.bind(this)); + this.removeRestartButtonChanged = this._settings.connect('changed::remove-restart-button', this._settingsChanged.bind(this)); + this.removePoweroffButtonChanged = this._settings.connect('changed::remove-poweroff-button', this._settingsChanged.bind(this)); + this.iconSizeChanged = this._settings.connect('changed::icon-size', this._settingsChanged.bind(this)); + this.borderRadiusChanged = this._settings.connect('changed::border-radius', this._settingsChanged.bind(this)); + this.paddingChanged = this._settings.connect('changed::padding', this._settingsChanged.bind(this)); + this.buttonsOrderChanged = this._settings.connect('changed::buttons-order', this._settingsChanged.bind(this)); + } + +_onDestroy() { + + const disconnectArray = [ + this.colorChanged, + this.useCustomColorChanged, + this.removeSuspendButtonChanged, + this.removeLogoutButtonChanged, + this.removeRestartButtonChanged, + this.removePoweroffButtonChanged, + this.iconSizeChanged, + this.borderRadiusChanged, + this.paddingChanged, + this.buttonsOrderChanged + ] + + for (let i = 0; i < disconnectArray.length; i++) { + if(disconnectArray[i]) { + this._settings.disconnect(disconnectArray[i]) + disconnectArray[i] = 0; } + } + + if(this._resetHoverTimeoutID) { + GLib.source_remove(this._resetHoverTimeoutID); + this._resetHoverTimeoutID = null; + } + + if(this._showLabelTimeoutID) { + GLib.source_remove(this._showLabelTimeoutID); + this._showLabelTimeoutID = null; + } + } + +_settingsChanged() { + SystemMenu.box.remove_actor(item); + this._createMenu(); + } +}); + +function init() { +} + +let modifiedMenu; + +function enable() { +SessionManager = GnomeSession.SessionManager(); +modifiedMenu = new _systemMenuButtons(); +} + +function disable() { + SystemMenu.box.remove_actor(item); + + if(SessionManager) { + SessionManager = null; + } + + modifiedMenu._onDestroy(); + modifiedMenu = null; + + SystemMenu.actor.insert_child_at_index(System._orientationLockItem, SystemMenu.numMenuItems); + SystemMenu.actor.insert_child_at_index(System._settingsItem, SystemMenu.numMenuItems); + SystemMenu.actor.insert_child_at_index(System._lockScreenItem, SystemMenu.numMenuItems); + SystemMenu.actor.insert_child_at_index(System._sessionSubMenu, SystemMenu.numMenuItems); +} + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/metadata.json new file mode 100644 index 0000000..f39dac9 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/metadata.json @@ -0,0 +1,14 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Rounded System Menu Buttons", + "name": "Rounded System Menu Buttons", + "settings-schema": "org.gnome.shell.extensions.round-system-menu-buttons", + "shell-version": [ + "40", + "41", + "42" + ], + "url": "https://github.com/PRATAP-KUMAR/rounded-system-menu-buttons", + "uuid": "roundedSystemMenuButtons@pratap.fastmail.fm", + "version": 20 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/prefs.js new file mode 100644 index 0000000..da92b86 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/prefs.js @@ -0,0 +1,492 @@ +const GLib = imports.gi.GLib; +const Gtk = imports.gi.Gtk; +const Gdk = imports.gi.Gdk; + +const ExtensionUtils = imports.misc.extensionUtils; + +const initialArray = [ + 'ORIENTATION BUTTON', + 'SETTINGS BUTTON', + 'LOCK BUTTON', + 'SUSPEND BUTTON', + 'SWITCH_USER BUTTON', + 'LOGOUT BUTTON', + 'RESTART BUTTON', + 'POWER BUTTON' + ] + +const GTK_VERSION = Gtk.get_major_version(); +let add; +let addRow; + if(GTK_VERSION == 4) { + add = 'append'; + addRow = 'set_child'; + } else { + add = 'add'; + addRow = 'add'; } + +function init() { +} + +function buildPrefsWidget() { + let widget = new PrefsWidget(); + if(GTK_VERSION == 3) { + widget.widget.show_all(); } + return widget.widget; +} + +class PrefsWidget { + constructor() { + this._settings = ExtensionUtils.getSettings(); + + this.BC_button = new Gtk.ColorButton(); + this._setButtonColor(); + + this.notebook = new Gtk.Notebook({ visible: true }); + + this.widget = new Gtk.Grid({ visible: true, column_homogeneous: true }); + this.notebook = new Gtk.Notebook({ visible: true }); + + this.listBox = []; + + this.listBox = new Gtk.ListBox({ visible: true }); + this.listBox.set_selection_mode(0); + + this.widget.attach(this.notebook, 0, 0, 1, 1); + + // Basic Settings Page + + let grid = new Gtk.Grid({ + column_spacing: 12, row_spacing: 12, + column_homogeneous: true, + hexpand: true, vexpand: true, + margin_start: 14, margin_end: 14, margin_top: 14, margin_bottom: 14, + visible: true + }); + + + let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 10, visible: true }); + + grid.attach(vbox, 0, 0, 3, 1); + + vbox[add](this.selectButtonColor()); + vbox[add](this.customColorButton()); + vbox[add](this.adjustIconSize()); + vbox[add](this.adjustPadding()); + vbox[add](this.adjustBorderRadius()); + vbox[add](this.resetButton()); + vbox[add](new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL, margin_bottom: 10, margin_top: 10 })); + vbox[add](this.removeSuspendButton()); + vbox[add](this.removeLogoutButton()); + vbox[add](this.removeRestartButton()); + vbox[add](this.removePoweroffButton()); + vbox[add](new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL, margin_bottom: 10, margin_top: 10 })); + vbox[add](this.tip()); + vbox[add](this.command()); + + this.notebook.append_page(grid, new Gtk.Label({ label: 'Basic Settings', visible: true, hexpand: true })); + + // End of Basic Settings Page + + // Arrange Button Order Page + + this.Buttons = []; + this.finalArray = []; + + let grid2 = new Gtk.Grid({ + column_spacing: 12, row_spacing: 12, + column_homogeneous: true, + hexpand: true, vexpand: true, + margin_start: 14, margin_end: 14, margin_top: 14, margin_bottom: 14, + visible: true + }); + + //let topHbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 20, visible: true }); + //grid.attach(topHbox, 0, 0, 2, 1); + + this.listBox = new Gtk.ListBox({ visible: true }); + this.listBox.set_selection_mode(0); + + this._prepareRow(initialArray); + this._saveOrder(); + this._removeListBox(); + + let BUTTONS_ORDER = this._settings.get_value('buttons-order').deepUnpack(); + let FINALARRAY = []; + + for (let i = 0; i < initialArray.length; i ++) { + let text = initialArray[BUTTONS_ORDER[i]-1] + FINALARRAY.push(text); + } + + this._prepareRow(FINALARRAY); + + grid2.attach(this.listBox, 0, 1, 1, 1); + + let RESET = new Gtk.Button(); + RESET.set_label("Reset 'Buttons Order' to Extensions Default."); + RESET.connect("clicked", () => { this._removeListBox(); + this._prepareRow(initialArray); + const value = new GLib.Variant('ai', [1, 2, 3, 4, 5, 6, 7, 8]); + this._settings.set_value('buttons-order', value); + }); + + grid2.attach(RESET, 0, 2, 1, 1); + + this.notebook.append_page(grid2, new Gtk.Label({ label: "Arrange 'Buttons Order'", visible: true, hexpand: true })); + + } + + // End of Arrange Button Order Page + +_prepareRow(ARRAY) { + + for(let i = 0; i < ARRAY.length; i++) { + + let row = new Gtk.ListBoxRow({ visible: true }); + + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, visible: true }); + + row[addRow](hbox); + + let TEXT = new Gtk.Button({ hexpand: true, margin_end: 10 }); + TEXT.set_label(ARRAY[i]); + + let ImageButton = new Gtk.Button({ margin_end: 10 }); + let B; + + let A = 'rotation-allowed-symbolic'; + + GTK_VERSION == 4 ? + B = 'org.gnome.Settings-symbolic' : B = 'system-settings-symbolic'; + + let C = 'changes-prevent-symbolic'; + let D = 'media-playback-pause-symbolic'; + let E = 'system-switch-user-symbolic'; + let F = 'system-log-out-symbolic'; + let G = 'system-reboot-symbolic'; + let H = 'system-shutdown-symbolic'; + + if(TEXT.get_label() == initialArray[0]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(A) : ImageButton.set_image(new Gtk.Image({ icon_name: A })); + if(TEXT.get_label() == initialArray[1]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(B) : ImageButton.set_image(new Gtk.Image({ icon_name: B })); + if(TEXT.get_label() == initialArray[2]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(C) : ImageButton.set_image(new Gtk.Image({ icon_name: C })); + if(TEXT.get_label() == initialArray[3]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(D) : ImageButton.set_image(new Gtk.Image({ icon_name: D })); + if(TEXT.get_label() == initialArray[4]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(E) : ImageButton.set_image(new Gtk.Image({ icon_name: E })); + if(TEXT.get_label() == initialArray[5]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(F) : ImageButton.set_image(new Gtk.Image({ icon_name: F })); + if(TEXT.get_label() == initialArray[6]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(G) : ImageButton.set_image(new Gtk.Image({ icon_name: G })); + if(TEXT.get_label() == initialArray[7]) + GTK_VERSION == 4 ? ImageButton.set_icon_name(H) : ImageButton.set_image(new Gtk.Image({ icon_name: H })); + + let upButton = new Gtk.Button({margin_end: 10}); + GTK_VERSION == 4 ? upButton.set_icon_name('go-up-symbolic') : upButton.set_image(new Gtk.Image({ icon_name: 'go-up-symbolic' })); + upButton.connect("clicked", () => { this._moveUp(i) }); + + let downButton = new Gtk.Button(); + GTK_VERSION == 4 ? downButton.set_icon_name('go-down-symbolic') : downButton.set_image(new Gtk.Image({ icon_name: 'go-down-symbolic' })); + downButton.connect("clicked", () => { this._moveDown(i) }); + + hbox[add](ImageButton); + hbox[add](TEXT); + hbox[add](upButton); + hbox[add](downButton); + + this.listBox[add](row) + } + + } + +_arraymove(array, fromIndex, toIndex) { + let element = array[fromIndex]; + array.splice(fromIndex, 1); + array.splice(toIndex, 0, element); + } + +_saveOrder () { + + if(GTK_VERSION == 4) { + for (let i = 0; i < initialArray.length; i++) { + let entry = this.listBox.get_row_at_index(i).get_child().get_first_child(); + entry = entry.get_next_sibling(); + let label = entry.get_label(); + this.Buttons.push(label); + } + } else { + for (let i = 0; i < initialArray.length; i++) { + let label = this.listBox.get_row_at_index(i).get_child().get_children()[1].get_label(); + this.Buttons.push(label); + } + } + + } + +_removeListBox () { + if(GTK_VERSION == 4) { + let child = this.listBox.get_first_child(); + while (child != null) { + let next = child.get_next_sibling(); + this.listBox.remove(child); + child = next; + } + } else { + this.listBox.foreach((element) => this.listBox.remove(element)); + } + } + +_moveUp (i) { + this.Buttons = []; + this._saveOrder(); + + this._removeListBox(); + + if(i == 0) { + this._arraymove(this.Buttons, 0, 7); + } else { + this._arraymove(this.Buttons, i, i-1) } + + this._prepareRow(this.Buttons); + + this.finalArray = []; + + for (let i = 0; i < initialArray.length; i ++) { + let index = initialArray.indexOf(this.Buttons[i]) + 1; + this.finalArray.push(index); + } + + const value = new GLib.Variant('ai', this.finalArray); + this._settings.set_value('buttons-order', value); + } + +_moveDown (i) { + this.Buttons = []; + this._saveOrder(); + + this._removeListBox(); + + if(i == 7) { + this._arraymove(this.Buttons, 7, 0); + } else { + this._arraymove(this.Buttons, i, i+1) } + + this._prepareRow(this.Buttons); + + this.finalArray = []; + + for (let i = 0; i < initialArray.length; i ++) { + let index = initialArray.indexOf(this.Buttons[i]) + 1; + this.finalArray.push(index); + } + + const value = new GLib.Variant('ai', this.finalArray); + this._settings.set_value('buttons-order', value); + } + +_setButtonColor() { + let rgba = new Gdk.RGBA(); + let hexString = this._settings.get_string('color'); + rgba.parse(hexString); + this.BC_button.set_rgba(rgba); + } + + +_cssHexString(css) { + let rrggbb = '#'; + let start; + for(let loop = 0; loop < 3; loop++) { + let end = 0; + let xx = ''; + for(let loop = 0; loop < 2; loop++) { + while(true) { + let x = css.slice(end, end + 1); + if(x == '(' || x == ',' || x == ')') + break; + end = end + 1; + } + if(loop == 0) { + end = end + 1; + start = end; + } + } + xx = parseInt(css.slice(start, end)).toString(16); + if(xx.length == 1) + xx = '0' + xx; + rrggbb = rrggbb + xx; + css = css.slice(end); + } + return rrggbb; + } + +_onPanelColorChanged() { + let rgba = this.BC_button.get_rgba(); + let css = rgba.to_string(); + let hexString = this._cssHexString(css); + this._settings.set_string('color', hexString); + } + +selectButtonColor() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5, halign: Gtk.Align.END }); + + this.BC_button.connect('notify::rgba', ()=> this._onPanelColorChanged() ); + + hbox[add](this.BC_button); + + return hbox; + } + +customColorButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let customColorButtonLabel = new Gtk.Label({ label: "Use Custom Color for Buttons", xalign: 0, hexpand: true }); + + this.cCBToggleSwitch = new Gtk.Switch({ active: this._settings.get_boolean('use-custom-color') }); + this.cCBToggleSwitch.connect('notify::active', (button) => { this._settings.set_boolean('use-custom-color', button.active); }); + + hbox[add](customColorButtonLabel); + hbox[add](this.cCBToggleSwitch) + + return hbox; + } + +removeSuspendButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let removeSuspendButtonLabel = new Gtk.Label({ label: "Remove Suspend Button", xalign: 0, hexpand: true }); + + this.rSBLToggleSwitch = new Gtk.Switch({ active: this._settings.get_boolean('remove-suspend-button') }); + this.rSBLToggleSwitch.connect('notify::active', (button) => { this._settings.set_boolean('remove-suspend-button', button.active); }); + + hbox[add](removeSuspendButtonLabel); + hbox[add](this.rSBLToggleSwitch) + + return hbox; + } + +removeLogoutButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let removeLogoutButtonLabel = new Gtk.Label({ label: "Remove Logout Button", xalign: 0, hexpand: true }); + + this.rLBLToggleSwitch = new Gtk.Switch({ active: this._settings.get_boolean('remove-logout-button') }); + this.rLBLToggleSwitch.connect('notify::active', (button) => { this._settings.set_boolean('remove-logout-button', button.active); }); + + hbox[add](removeLogoutButtonLabel); + hbox[add](this.rLBLToggleSwitch) + + return hbox; + } + +removeRestartButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let removeRestartButtonLabel = new Gtk.Label({ label: "Remove Restart Button", xalign: 0, hexpand: true }); + + this.rRBLToggleSwitch = new Gtk.Switch({ active: this._settings.get_boolean('remove-restart-button') }); + this.rRBLToggleSwitch.connect('notify::active', (button) => { this._settings.set_boolean('remove-restart-button', button.active); }); + + hbox[add](removeRestartButtonLabel); + hbox[add](this.rRBLToggleSwitch); + + return hbox; + } + +removePoweroffButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let removePoweroffButtonLabel = new Gtk.Label({ label: "Remove Poweroff Button", xalign: 0, hexpand: true }); + + this.rPBLToggleSwitch = new Gtk.Switch({ active: this._settings.get_boolean('remove-poweroff-button') }); + this.rPBLToggleSwitch.connect('notify::active', (button) => { this._settings.set_boolean('remove-poweroff-button', button.active); }); + + hbox[add](removePoweroffButtonLabel); + hbox[add](this.rPBLToggleSwitch) + + return hbox; + } + +adjustIconSize() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let IS_label = new Gtk.Label({ label: "Adjust Icon Size", xalign: 0, hexpand: true }); + + this.IS_button = new Gtk.SpinButton(); + this.IS_button.set_range(12, 20); + this.IS_button.set_value(this._settings.get_int('icon-size')); + this.IS_button.set_increments(2, 4); + this.IS_button.connect('value-changed', (entry) => { this._settings.set_int('icon-size', entry.get_value()); }); + + hbox[add](IS_label); + hbox[add](this.IS_button); + + return hbox; + } + +adjustPadding() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let PD_label = new Gtk.Label({ label: "Adjust Padding", xalign: 0, hexpand: true }); + + this.PD_button = new Gtk.SpinButton(); + this.PD_button.set_range(0, 16); + this.PD_button.set_value(this._settings.get_int('padding')); + this.PD_button.set_increments(2, 4); + this.PD_button.connect('value-changed', (entry) => { this._settings.set_int('padding', entry.get_value()); }); + + hbox[add](PD_label); + hbox[add](this.PD_button); + + return hbox; + } + +adjustBorderRadius() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5 }); + let BR_label = new Gtk.Label({ label: "Adjust Border Raidus", xalign: 0, hexpand: true }); + this.BR_button = new Gtk.SpinButton(); + this.BR_button.set_range(0, 32); + this.BR_button.set_value(this._settings.get_int('border-radius')); + this.BR_button.set_increments(2, 4); + this.BR_button.connect('value-changed', (entry) => { this._settings.set_int('border-radius', entry.get_value()); }); + + hbox[add](BR_label); + hbox[add](this.BR_button); + + return hbox; + } + +resetButton() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5, halign: Gtk.Align.CENTER }); + let resetButton = new Gtk.Button(); + resetButton.set_label("Reset to Extensions's Default Size'es By Cliking this Button"); + resetButton.connect('clicked', ()=> { + this._settings.set_int('icon-size', 16); + this._settings.set_int('padding', 8); + this._settings.set_int('border-radius', 16); + this.IS_button.set_value(this._settings.get_int('icon-size')); + this.PD_button.set_value(this._settings.get_int('padding')); + this.BR_button.set_value(this._settings.get_int('border-radius')); + + }); + + hbox[add](resetButton); + + return hbox; + } + +tip() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5, halign: Gtk.Align.START }); + let tipLabel = new Gtk.Label({ label: + "you can tweak the BACKGROUND COLOR of these system menu buttons by edititng this extensions stylesheet.css file.\n\ +Run below command to open the styles sheet file." }); + + hbox[add](tipLabel); + + return hbox; + } + +command() { + let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5, margin_bottom: 20, halign: Gtk.Align.START }); + let command = new Gtk.Label({ label: "gedit $HOME/.local/share/gnome-shell/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/stylesheet.css", useMarkup: true, selectable: true }); + + hbox[add](command); + + return hbox; + } +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/gschemas.compiled new file mode 100644 index 0000000..2c30390 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.round-system-menu-buttons.gschema.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.round-system-menu-buttons.gschema.xml new file mode 100644 index 0000000..c6190b5 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.round-system-menu-buttons.gschema.xml @@ -0,0 +1,69 @@ + + + + + +[ 1, 2, 3, 4, 5, 6, 7, 8 ] +Default Order +Default Order + + + +false +Turn ON if you wish to use Custom Color. +Custom Color + + + +'#000000' +color +color + + + + +16 +icon size +icon size + + + + +8 +padding +icon size + + + + +16 +border radius +icon size + + + +false +Remove Suspend Button +Remove Suspend Button + + + +false +Remove Logout Button +Remove Logout Button + + + +false +Remove Restart Button +Remove Restart Button + + + +false +Remove poweroff Button +Remove poweroff Button + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/stylesheet.css b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/stylesheet.css new file mode 100644 index 0000000..309593c --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/roundedSystemMenuButtons@pratap.fastmail.fm/stylesheet.css @@ -0,0 +1,13 @@ +/* Add your custom extension styling here */ + +.rounded-menu-buttons { + background-color: #353535 + } + +.rounded-menu-buttons:hover, .rounded-menu-buttons:focus { + background-color: rgba(255, 255, 255, 0.1); + } + +.rounded-menu-buttons:active { + background-color: #1b6acb; + } diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/base.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/base.js new file mode 100644 index 0000000..6db500f --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/base.js @@ -0,0 +1,759 @@ +/******************************************************************************* + * 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 http://www.gnu.org/licenses/. + * ***************************************************************************** + * Original Author: Gopi Sankar Karmegam + ******************************************************************************/ +/* jshint moz:true */ + +const { GObject, GLib, Gvc } = imports.gi; + +const Signals = imports.signals; + +const PopupMenu = imports.ui.popupMenu; +const VolumeMenu = imports.ui.status.volume; +const Main = imports.ui.main; +const MessageTray = imports.ui.messageTray; + +const Config = imports.misc.config; +const ExtensionUtils = imports.misc.extensionUtils; +const Gettext = imports.gettext; + +const Me = ExtensionUtils.getCurrentExtension(); +const Lib = Me.imports.convenience; +const Prefs = Me.imports.prefs; + +ExtensionUtils.initTranslations(Me.metadata["gettext-domain"]); +const Domain = Gettext.domain(Me.metadata["gettext-domain"]); +const _ = Domain.gettext; +//const _ = Gettext.gettext; +const _d = Lib._log; +const getActor = Lib.getActor; + +const DISPLAY_OPTIONS = Prefs.DISPLAY_OPTIONS; +const SignalManager = Lib.SignalManager; +const isShellAbove34 = (parseFloat(Config.PACKAGE_VERSION) >= 3.34); + +var ProfileMenuItem40 = class + extends PopupMenu.PopupMenuItem { + _init(title, profileName) { + if (super._init) { + super._init(title); + } + _d("ProfileMenuItem: _init:" + title); + this._initialise(profileName); + } + + _initialise(profileName) { + this.profileName = profileName; + this._ornamentLabel.set_style("min-width: 3em;margin-left: 3em;"); + this.setProfileActive(false); + } + + setProfileActive(active) { + if (active) { + this.setOrnament(PopupMenu.Ornament.DOT); + // this._ornamentLabel.text = "\u2727"; + this._ornamentLabel.text = "\u266A"; + if (this.add_style_pseudo_class) { + this.remove_style_pseudo_class('insensitive'); + } + else { + getActor(this).remove_style_pseudo_class('insensitive'); + } + } + else { + this.setOrnament(PopupMenu.Ornament.NONE); + if (this.add_style_pseudo_class) { + this.add_style_pseudo_class('insensitive'); + } + else { + getActor(this).add_style_pseudo_class('insensitive'); + } + } + } + + setVisibility(visibility) { + getActor(this).visible = visibility; + } +} + +var ProfileMenuItem32 = class + extends ProfileMenuItem40 { + constructor(title, profileName){ + _d("ProfileMenuItem: constructor:" + title); + super(title); + this._initialise(profileName); + } +} + +var SoundDeviceMenuItem40 = class extends PopupMenu.PopupImageMenuItem { + _init(id, title, icon_name, profiles) { + if (super._init) { + super._init(title, icon_name); + } + _d("SoundDeviceMenuItem: _init:" + title); + this._initialise(id, title, icon_name, profiles); + } + + _initialise(id, title, icon_name, profiles) { + this.id = id; + this.title = title; + this.icon_name = icon_name; + this.profiles = (profiles) ? profiles : []; + + this.profilesitems = new Map(); + for (let profile of this.profiles) { + let profileName = profile.name; + if (!this.profilesitems.has(profileName)) { + let pItem = new ProfileMenuItem(_("Profile: ") + profile.human_name, profileName); + this.profilesitems.set(profileName, pItem); + pItem.connect('activate', () => { + _d("Activating Profile:" + id + profileName); + this.emit("profile-activated", this.id, profileName); + }); + } + } + + this.connect('activate', () => { + _d("Device Change request for " + id); + _d("Emitting Signal..."); + this.emit("device-activated", this.id); + }); + this.available = true; + this.activeProfile = ""; + this.activeDevice = false; + this._displayOption = DISPLAY_OPTIONS.INITIAL; + getActor(this).visible = false; + } + + isAvailable() { + return this.available; + } + + setAvailable(_ac) { + this.available = _ac; + } + + setActiveProfile(_p) { + if (_p && this.activeProfile != _p) { + if (this.profilesitems.has(this.activeProfile)) { + this.profilesitems.get(this.activeProfile).setProfileActive(false); + } + this.activeProfile = _p; + if (this.profilesitems.has(_p)) { + this.profilesitems.get(_p).setProfileActive(true); + } + } + } + + setVisibility(_v) { + getActor(this).visible = _v; + if (!_v) { + this.profilesitems.forEach((p) => p.setVisibility(false)); + } + }; + + setTitle(_t) { + _d("SoundDeviceMenuItem: " + "setTitle: " + this.title + "->" + _t); + this.title = _t; + this.label.text = _t; + } + + isVisible() { + return getActor(this).visible; + } + + setActiveDevice(_a) { + this.activeDevice = _a; + if (!_a) { + this.setOrnament(PopupMenu.Ornament.NONE); + } + else { + this.setOrnament(PopupMenu.Ornament.CHECK); + this._ornamentLabel.text = '\u266B'; + } + } + + setProfileVisibility(_v) { + this.profilesitems.forEach(p => + p.setVisibility(_v && this.canShowProfile())); + } + + canShowProfile() { + return (this.isVisible() && this.profilesitems.size >= 1); + } + + setDisplayOption(displayOption) { + _d("Setting Display Option to : " + displayOption); + this._displayOption = displayOption; + } + + getDisplayOption() { + return this._displayOption; + } +} + +var SoundDeviceMenuItem32 = class extends SoundDeviceMenuItem40 { + constructor(id, title, icon_name, profiles) { + _d("SoundDeviceMenuItem: constructor:" + title); + super(title, icon_name); + this._initialise(id, title, icon_name, profiles); + } +} + +var SoundDeviceMenuItem; +var ProfileMenuItem; +if (isShellAbove34) { + SoundDeviceMenuItem = SoundDeviceMenuItem40; + ProfileMenuItem = ProfileMenuItem40; + ProfileMenuItem = GObject.registerClass({ GTypeName: 'ProfileMenuItem' }, ProfileMenuItem); + + SoundDeviceMenuItem = GObject.registerClass({ + GTypeName: "SoundDeviceMenuItem", + Signals: { + "device-activated": { + param_types: [GObject.TYPE_INT] + }, + "profile-activated": { + param_types: [GObject.TYPE_INT, GObject.TYPE_STRING] + } + } + }, SoundDeviceMenuItem); +} +else +{ + SoundDeviceMenuItem = SoundDeviceMenuItem32; + ProfileMenuItem = ProfileMenuItem32; +} + +var SoundDeviceChooserBase = class SoundDeviceChooserBase { + constructor(deviceType) { + _d("SDC: init"); + this.menuItem = new PopupMenu.PopupSubMenuMenuItem(_("Extension initialising..."), true); + this.deviceType = deviceType; + this._devices = new Map(); + let _control = this._getMixerControl(); + this._settings = ExtensionUtils.getSettings(); + _d("Constructor:" + deviceType); + + this._setLog(); + this._signalManager = new SignalManager(); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.ENABLE_LOG, this._setLog.bind(this)); + + if (_control.get_state() == Gvc.MixerControlState.READY) { + this._onControlStateChanged(_control); + } + else { + this._controlStateChangeSignal = this._signalManager.addSignal(_control, "state-changed", this._onControlStateChanged.bind(this)); + } + + this._signalManager.addSignal(this.menuItem.menu, "open-state-changed", this._onSubmenuOpenStateChanged.bind(this)); + this._signalManager.addSignal(this.menuItem, "notify::visible", () => {this.emit('update-visibility', getActor(this.menuItem).visible);}); + } + + _getMixerControl() { return VolumeMenu.getMixerControl(); } + + _setLog() { Lib.setLog(this._settings.get_boolean(Prefs.ENABLE_LOG)); } + + _onControlStateChanged(control) { + if (control.get_state() == Gvc.MixerControlState.READY) { + + this._signalManager.addSignal(control, this.deviceType + "-added", this._deviceAdded.bind(this)); + this._signalManager.addSignal(control, this.deviceType + "-removed", this._deviceRemoved.bind(this)); + this._signalManager.addSignal(control, "active-" + this.deviceType + "-update", this._deviceActivated.bind(this)); + + this._signalManager.addSignal(this._settings, "changed::" + Prefs.HIDE_ON_SINGLE_DEVICE, this._setChooserVisibility.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.SHOW_PROFILES, this._setProfileVisibility.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.ICON_THEME, this._setIcons.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.HIDE_MENU_ICONS, this._setIcons.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.PORT_SETTINGS, this._resetDevices.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.OMIT_DEVICE_ORIGIN, this._refreshDeviceTitles.bind(this)); + + this._show_device_signal = Prefs["SHOW_" + this.deviceType.toUpperCase() + "_DEVICES"]; + + this._signalManager.addSignal(this._settings, "changed::" + this._show_device_signal, this._setVisibility.bind(this)); + + this._portsSettings = Prefs.getPortsFromSettings(this._settings); + + /** + * There is no direct way to get all the UI devices from + * mixercontrol. When enabled after shell loads, the signals + * will not be emitted, a simple hack to look for ids, until any + * uidevice is not found. The UI devices are always serialed + * from from 1 to n + */ + + let id = 0; + + let dummyDevice = new Gvc.MixerUIDevice(); + let maxId = dummyDevice.get_id(); + + _d("Max Id:" + maxId); + + while (++id < maxId) { + this._deviceAdded(control, id); + } + let defaultStream = this.getDefaultStream(control); + if (defaultStream) { + let defaultDevice = control.lookup_device_from_stream(defaultStream); + if (defaultDevice) { + this._deviceActivated(control, defaultDevice.get_id()); + } + } + + if (this._controlStateChangeSignal) { + this._controlStateChangeSignal.disconnect(); + delete this._controlStateChangeSignal; + } + this._setVisibility(); + } + } + + _onSubmenuOpenStateChanged(_menu, opened) { + _d(this.deviceType + "-Submenu is now open?: " + opened); + if (opened) { // Actions when submenu is opening + this._setActiveProfile(); + } + else { // Actions when submenu is closing + } + } + + _deviceAdded(control, id, dontcheck) { + let obj = this._devices.get(id); + let uidevice = this.lookupDeviceById(control, id); + + _d("Added - " + id); + + if (!obj) { + if (this._isDeviceInValid(uidevice)) { + return null; + } + + let title = this._getDeviceTitle(uidevice); + + let icon = uidevice.get_icon_name(); + if (icon == null || icon.trim() == "") + icon = this.getDefaultIcon(); + icon = this._getIcon(icon); + + obj = new SoundDeviceMenuItem(id, title, icon, Lib.getProfiles(control, uidevice)); + obj.connect("device-activated", (item, id) => this._changeDeviceBase(id)); + obj.connect("profile-activated", (item, id, name) => this._profileChangeCallback(id, name)); + + this.menuItem.menu.addMenuItem(obj); + obj.profilesitems.forEach(i => this.menuItem.menu.addMenuItem(i)); + + this._devices.set(id, obj); + } + else if (!obj.isAvailable()) + obj.setAvailable(true); + else + return; + + + _d("Device Name:" + obj.title); + + _d("Added: " + id + ":" + uidevice.description + ":" + uidevice.port_name + ":" + uidevice.origin); + + let stream = control.get_stream_from_device(uidevice); + if (stream) { + obj.setActiveProfile(uidevice.get_active_profile()); + } + + if (!dontcheck && !this._canShowDevice(control, uidevice, obj, uidevice.port_available)) { + _d("This device is hidden in settings, lets hide...") + this._deviceRemoved(control, id, true); + } + else { + this._setChooserVisibility(); + this._setVisibility(); + } + } + + _profileChangeCallback(id, profileName) { + let control = this._getMixerControl(); + let uidevice = this.lookupDeviceById(control, id); + if (!uidevice) { + this._deviceRemoved(control, id); + } + else { + _d("i am setting profile, " + profileName + ":" + uidevice.description + ":" + uidevice.port_name); + if (id != this._activeDeviceId) { + _d("Changing active device to " + uidevice.description + ":" + uidevice.port_name); + this._changeDeviceBase(id, control); + } + control.change_profile_on_selected_device(uidevice, profileName); + //this._setDeviceActiveProfile(control, this._devices.get(id)); //"Races" change_profile_...(...) and reports the old state + } + } + + _deviceRemoved(control, id, dontcheck) { + let obj = this._devices.get(id); + + if (obj && obj.isAvailable()) { + _d("Removed: " + id + ":" + obj.title); + /* + let uidevice = this.lookupDeviceById(control,id); + if (!dontcheck && this._canShowDevice(control, uidevice, obj, false)) { + _d('Device removed, but not hiding as its set to be shown always'); + return; + }*/ + obj.setVisibility(false); + obj.setAvailable(false); + + /* + if (this.deviceRemovedTimout) { + GLib.source_remove(this.deviceRemovedTimout); + this.deviceRemovedTimout = null; + } + */ + /** + * If the active uidevice is removed, then need to activate the + * first available uidevice. However for some cases like Headphones, + * when the uidevice is removed, Speakers are automatically + * activated. So, lets wait for sometime before activating. + */ + /* THIS MAY NOT BE NEEDED AS SHELL SEEMS TO ACTIVATE NEXT DEVICE + this.deviceRemovedTimout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1500, function() { + _d("Device Removed timeout"); + if (obj === this._activeDevice) { + let device = Object.keys(this._devices).map((id) => this._devices[id]).find(({active}) => active === true); + if(device){ + this._changeDeviceBase(device.id, this._getMixerControl()); + } + } + this.deviceRemovedTimout = null; + return false; + }.bind(this)); + */ + this._setChooserVisibility(); + this._setVisibility(); + } + } + + _deviceActivated(control, id) { + _d("Activated:- " + id); + let obj = this._devices.get(id); + if (!obj) { + _d("Activated device not found in the list of devices, try to add"); + this._deviceAdded(control, id); + obj = this._devices.get(id); + } + if (obj && id != this._activeDeviceId) { + _d("Activated: " + id + ":" + obj.title); + if (this._settings.get_boolean(Prefs.CANNOT_ACTIVATE_HIDDEN_DEVICE) + && obj.getDisplayOption() === DISPLAY_OPTIONS.HIDE_ALWAYS) { + _d("Preference does not allow this hidden device to be activated, fallback to the previous aka original device"); + let device = null; + + if (this._activeDeviceId) { + device = this._devices.get(this._activeDeviceId); + } + else { + device = Array.from(this._devices.values()).find(x => x.isAvailable()); + } + + if (device) { + _notify(Me.metadata["name"] + " " + _("Extension changed active sound device."), + _("Activated device is hidden in Port Settings.") + " \n" + + _("Deactivated Device: ") + obj.title + " \n" + _("Activated Device: ") + device.title + " \n" + + _("Disable in extension preferences to avoid this behaviour."), + device.icon_name); + this._changeDeviceBase(device.id, control); + } + else { + this._activateDeviceMenuItem(control, id, obj); + } + + } + else { + this._activateDeviceMenuItem(control, id, obj); + } + } + } + + _activateDeviceMenuItem(control, id, obj) { + let prevActiveDevce = this._activeDeviceId; + this._activeDeviceId = id; + if (prevActiveDevce) { + let prevObj = this._devices.get(prevActiveDevce); + if (prevObj) { + prevObj.setActiveDevice(false); + if (prevObj.getDisplayOption() === DISPLAY_OPTIONS.HIDE_ALWAYS) { + _d("Hiding previously activated device as it is set to hidden always"); + this._deviceRemoved(control, prevActiveDevce, true); + } + } + } + obj.setActiveDevice(true); + if (!obj.isAvailable()) { + _d("Activated device hidden, try to add"); + this._deviceAdded(control, id); + } + + this.menuItem.label.text = obj.title; + + if (!this._settings.get_boolean(Prefs.HIDE_MENU_ICONS)) { + this.menuItem.icon.icon_name = obj.icon_name; + } else { + this.menuItem.icon.gicon = null; + } + } + + _changeDeviceBase(id, control) { + if (!control) { + control = this._getMixerControl(); + } + let uidevice = this.lookupDeviceById(control, id); + if (uidevice) { + this.changeDevice(control, uidevice); + } + else { + this._deviceRemoved(control, id); + } + } + + _setActiveProfile() { + let control = this._getMixerControl(); + this._devices.forEach(device => { + if (device.isAvailable()) { + this._setDeviceActiveProfile(control, device); + } + }); + } + + _setDeviceActiveProfile(control, device) { + if (!device || !device.isAvailable()) { + return; + } + + let uidevice = this.lookupDeviceById(control, device.id); + if (!uidevice) { + this._deviceRemoved(control, device.id); + } + else { + let activeProfile = uidevice.get_active_profile(); + _d("Active Profile:" + activeProfile); + device.setActiveProfile(activeProfile); + } + } + + _getAvailableDevices() { + return Array.from(this._devices.values()).filter(x => x.isAvailable()); + } + + _getDeviceVisibility() { + let hideChooser = this._settings.get_boolean(Prefs.HIDE_ON_SINGLE_DEVICE); + let numAvailableDevices = this._getAvailableDevices().length; + if (hideChooser) { + return numAvailableDevices > 1; + } + else { + return numAvailableDevices > 0; + } + } + + _setChooserVisibility() { + let visibility = this._getDeviceVisibility(); + this._getAvailableDevices().forEach(x => x.setVisibility(visibility)) + + //getActor(this.menuItem._triangleBin).visible = visibility; + //getActor(this.menuItem).visible = visibility; + this._setProfileVisibility(); + this.setVisible(visibility); + } + + _setVisibility() { + if (!this._settings.get_boolean(this._show_device_signal)) + this.setVisible(false); + else + // if setting says to show device, check for any device, otherwise + // hide the "actor" + this.setVisible(this._getDeviceVisibility()); + } + + setVisible(visibility) { + getActor(this.menuItem).visible = visibility; + //this.emit('update-visibility', visibility); + } + + _setProfileVisibility() { + let visibility = this._settings.get_boolean(Prefs.SHOW_PROFILES); + this._getAvailableDevices().forEach(device => device.setProfileVisibility(visibility)); + } + + _getIcon(name) { + let iconsType = this._settings.get_string(Prefs.ICON_THEME); + switch (iconsType) { + case Prefs.ICON_THEME_COLORED: + return name; + case Prefs.ICON_THEME_MONOCHROME: + return name + "-symbolic"; + default: + //return "none"; + return null; + } + } + + _setIcons() { + // Set the icons in the selection list + let control = this._getMixerControl(); + this._devices.forEach((device, id) => { + let uidevice = this.lookupDeviceById(control, id); + if (uidevice) { + let icon = uidevice.get_icon_name(); + if (icon == null || icon.trim() == "") + icon = this.getDefaultIcon(); + _d(icon + " _setIcons") + device.setIcon(this._getIcon(icon)); + } + }); + + // These indicate the active device, which is displayed directly in the + // Gnome menu, not in the list. + if (!this._settings.get_boolean(Prefs.HIDE_MENU_ICONS)) { + this.menuItem.icon.icon_name = this._getIcon(this._devices.get(this._activeDeviceId).icon_name); + } else { + this.menuItem.icon.icon_name = null; + } + } + + _getDeviceDisplayOption(control, uidevice, obj) { + let displayOption = DISPLAY_OPTIONS.DEFAULT; + if (uidevice && uidevice.port_name != null && uidevice.description != null) { + let stream = control.get_stream_from_device(uidevice); + let cardName = null; + if (stream) { + let cardId = stream.get_card_index(); + if (cardId != null) { + _d("Card Index:" + cardId); + let _card = Lib.getCard(cardId); + if (_card) { + cardName = _card.name; + } + else { + //card id found, but not available in list + return DISPLAY_OPTIONS.DEFAULT; + } + _d("Card Name:" + cardName); + } + } + + _d("P:" + uidevice.port_name + "==" + uidevice.description + "==" + cardName + "==" + uidevice.origin); + + let matchedPort = this._portsSettings.find(port => (port + && port.name == uidevice.port_name + && port.human_name == uidevice.description + && (!cardName || port.card_name == cardName) + && (cardName || port.card_description == uidevice.origin))); + + if (matchedPort) { + displayOption = matchedPort.display_option; + } + } + + obj && obj.setDisplayOption(displayOption); + + return displayOption; + } + + _canShowDevice(control, uidevice, obj, defaultValue) { + if (!uidevice || !this._portsSettings || uidevice.port_name == null + || uidevice.description == null || (this._activeDeviceId && this._activeDeviceId == uidevice.get_id())) { + return defaultValue; + } + + let displayOption = obj.getDisplayOption(); + if (displayOption === DISPLAY_OPTIONS.INITIAL) { + displayOption = this._getDeviceDisplayOption(control, uidevice, obj); + } + + if (displayOption === DISPLAY_OPTIONS.SHOW_ALWAYS) { + _d("Display Device due Preference:" + displayOption); + return true; + } + else if (displayOption === DISPLAY_OPTIONS.HIDE_ALWAYS) { + _d("Hide Device due Preference:" + displayOption); + return false; + } + else { + _d("Default Device due Preference:" + displayOption); + return defaultValue; + } + } + + _resetDevices() { + this._portsSettings = Prefs.getPortsFromSettings(this._settings); + let control = this._getMixerControl(); + this._devices.forEach((device, id) => { + device.setDisplayOption(DISPLAY_OPTIONS.INITIAL); + let uidevice = this.lookupDeviceById(control, id); + if (this._isDeviceInValid(uidevice)) + _d("Device is invalid"); + else if (this._canShowDevice(control, uidevice, device, uidevice.port_available)) + this._deviceAdded(control, id, true); + else + this._deviceRemoved(control, id, true); + }); + } + + _isDeviceInValid(uidevice) { + return (!uidevice || (uidevice.description != null && uidevice.description.match(/Dummy\s+(Output|Input)/gi))); + } + + _refreshDeviceTitles() { + let control = this._getMixerControl(); + this._devices.forEach((device, id) => { + let uidevice = this.lookupDeviceById(control, id); + let title = this._getDeviceTitle(uidevice); + + device.setTitle(title); + }); + + let activeDevice = this._devices.get(this._activeDeviceId); + this.menuItem.label.text = activeDevice.title; + } + + _getDeviceTitle(uidevice) { + let title = uidevice.description; + if (!this._settings.get_boolean(Prefs.OMIT_DEVICE_ORIGIN) && uidevice.origin != "") + title += " - " + uidevice.origin; + + return title; + } + + destroy() { + this._signalManager.disconnectAll(); + if (this.deviceRemovedTimout) { + GLib.source_remove(this.deviceRemovedTimout); + this.deviceRemovedTimout = null; + } + if (this.activeProfileTimeout) { + GLib.source_remove(this.activeProfileTimeout); + this.activeProfileTimeout = null; + } + this.menuItem.destroy(); + } + +}; + +Signals.addSignalMethods(SoundDeviceChooserBase.prototype); + +function _notify(msg, details, icon_name) { + let source = new MessageTray.Source(Me.metadata["name"], icon_name); + Main.messageTray.add(source); + let notification = new MessageTray.Notification(source, msg, details); + //notification.setTransient(true); + source.showNotification(notification); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/convenience.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/convenience.js new file mode 100644 index 0000000..4cc6027 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/convenience.js @@ -0,0 +1,357 @@ +/******************************************************************************* + * 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 . + * ***************************************************************************** + * Original Author: Gopi Sankar Karmegam + ******************************************************************************/ +/* jshint moz:true */ + +const ByteArray = imports.byteArray; +const { Gio, GLib } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; + +const Me = ExtensionUtils.getCurrentExtension(); +const Prefs = Me.imports.prefs; + +var DEBUG = false; + +var logWrap; +if (log != undefined) { + logWrap = log; +} +else { + logWrap = global.log +} + + +let cards; + +function getCard(card_index) { + if (!cards || Object.keys(cards).length == 0) { + refreshCards(); + } + return cards[card_index]; +} + +function getCardByName(card_name) { + if (!cards || Object.keys(cards).length == 0) { + refreshCards(); + } + return Object.keys(cards).map((index) => cards[index]).find(({ name }) => name === card_name); +} + +function getProfiles(control, uidevice) { + let stream = control.lookup_stream_id(uidevice.get_stream_id()); + if (stream) { + if (!cards || Object.keys(cards).length == 0 || !cards[stream.card_index]) { + refreshCards(); + } + if (cards && cards[stream.card_index]) { + _log("Getting profile form stream id " + uidevice.port_name); + let profiles; + if ((profiles = getProfilesForPort(uidevice.port_name, cards[stream.card_index]))) { + return profiles; + } + } + } + else { + /* Device is not active device, lets try match with port name */ + refreshCards(); + for (let card of Object.values(cards)) { + let profiles; + _log("Getting profile from cards " + uidevice.port_name + " for card id " + card.id); + if ((profiles = getProfilesForPort(uidevice.port_name, card))) { + return profiles; + } + } + } + return []; +} + +let ports; +function getPorts(refresh) { + if (!ports || ports.length == 0 || refresh) { + refreshCards(); + } + return ports; +} + +function isCmdFound(cmd) { + try { + let [result, out, err, exit_code] = GLib.spawn_command_line_sync(cmd); + return true; + } + catch (e) { + _log("ERROR: " + cmd + " execution failed. " + e); + return false; + } +} + +function refreshCards() { + cards = {}; + ports = []; + let _settings = ExtensionUtils.getSettings(); + let error = false; + let newProfLogic = _settings.get_boolean(Prefs.NEW_PROFILE_ID_DEPRECATED); + + /** This block should be removed in the next release along the setting schema correct */ + if (!newProfLogic) { + _settings.set_boolean(Prefs.NEW_PROFILE_ID, false); + _settings.reset(Prefs.NEW_PROFILE_ID_DEPRECATED); + } + else { + newProfLogic = _settings.get_boolean(Prefs.NEW_PROFILE_ID); + } + + if (newProfLogic) { + _log("New logic"); + let pyLocation = Me.dir.get_child("utils/pa_helper.py").get_path(); + let pythonExec = ["python", "python3", "python2"].find(cmd => isCmdFound(cmd)); + if (!pythonExec) { + _log("ERROR: Python not found. fallback to default mode"); + _settings.set_boolean(Prefs.NEW_PROFILE_ID, false); + Gio.Settings.sync(); + newProfLogic = false; + } + else { + try { + _log("Python found." + pythonExec); + let [result, out, err, exit_code] = GLib.spawn_command_line_sync(pythonExec + " " + pyLocation); + // _log("result" + result +" out"+out + " exit_code" + + // exit_code + "err" +err); + if (result && !exit_code) { + if (out instanceof Uint8Array) { + out = ByteArray.toString(out); + } + let obj = JSON.parse(out); + cards = obj["cards"]; + ports = obj["ports"]; + } + } + catch (e) { + error = true; + _log("ERROR: Python execution failed. fallback to default mode" + e); + _settings.set_boolean(Prefs.NEW_PROFILE_ID, false); + Gio.Settings.sync(); + } + } + } + //error = true; + if (!newProfLogic || error) { + _log("Old logic"); + try { + let env = GLib.get_environ(); + env = GLib.environ_setenv(env, "LANG", "C", true); + let [result, out, err, exit_code] = GLib.spawn_sync(null, ["pactl", "list", "cards"], env, GLib.SpawnFlags.SEARCH_PATH, null); + //_log(result+"--"+out+"--"+ err+"--"+ exit_code) + if (result && !exit_code) { + parseOutput(out); + } + } + catch (e) { + _log("ERROR: pactl execution failed. No ports/profiles will be displayed." + e); + } + } + //_log(Array.isArray(cards)); + //_log(JSON.stringify(cards)); + //_log(Array.isArray(ports)); + //_log(JSON.stringify(ports)); +} + +function parseOutput(out) { + let lines; + if (out instanceof Uint8Array) { + lines = ByteArray.toString(out).split("\n"); + } else { + lines = out.toString().split("\n"); + } + + let cardIndex; + let parseSection = "CARDS"; + let port; + let matches; + // _log("Unmatched line:" + out); + while (lines.length > 0) { + let line = lines.shift(); + + if ((matches = /^Card\s#(\d+)$/.exec(line))) { + cardIndex = matches[1]; + if (!cards[cardIndex]) { + cards[cardIndex] = { "index": cardIndex, "profiles": [], "ports": [] }; + } + } + else if ((matches = /^\t*Name:\s+(.*?)$/.exec(line)) && cards[cardIndex]) { + cards[cardIndex].name = matches[1]; + parseSection = "CARDS" + } + else if (line.match(/^\tProperties:$/) && parseSection == "CARDS") { + parseSection = "PROPS"; + } + else if (line.match(/^\t*Profiles:$/)) { + parseSection = "PROFILES"; + } + else if (line.match(/^\t*Ports:$/)) { + parseSection = "PORTS"; + } + else if (cards[cardIndex]) { + switch (parseSection) { + case "PROPS": + if ((matches = /alsa\.card_name\s+=\s+"(.*?)"/.exec(line))) { + cards[cardIndex].alsa_name = matches[1]; + } + else if ((matches = /device\.description\s+=\s+"(.*?)"/.exec(line))) { + cards[cardIndex].card_description = matches[1]; + } + break; + case "PROFILES": + if ((matches = /.*?((?:output|input)[^+]*?):\s(.*?)\s\(sinks:.*?(?:available:\s*(.*?))*\)/.exec(line))) { + let availability = matches[3] ? matches[3] : "yes" //If no availability in out, assume profile is available + + cards[cardIndex].profiles.push({ + "name": matches[1], + "human_name": matches[2], + "available": (availability === "yes") ? 1 : 0 + }); + } + break; + case "PORTS": + if ((matches = /\t*(.*?):\s(.*)\s\(.*?priority:/.exec(line))) { + port = { + "name": matches[1], + "human_name": matches[2], + "card_name": cards[cardIndex].name, + "card_description": cards[cardIndex].card_description + }; + cards[cardIndex].ports.push(port); + ports.push(port); + } + else if (port && (matches = /\t*Part of profile\(s\):\s(.*)/.exec(line))) { + let profileStr = matches[1]; + port.profiles = profileStr.split(", "); + port = null; + } + break; + } + } + } + if (ports) { + ports.forEach(p => { + p.direction = p.profiles + .filter(pr => pr.indexOf("+input:") == -1) + .some(pr => (pr.indexOf("output:") >= 0)) ? "Output" : "Input"; + }); + } +} + +var Signal = class Signal { + + constructor(signalSource, signalName, callback) { + this._signalSource = signalSource; + this._signalName = signalName; + this._signalCallback = callback; + } + + connect() { + this._signalId = this._signalSource.connect(this._signalName, this._signalCallback); + } + + disconnect() { + if (this._signalId) { + this._signalSource.disconnect(this._signalId); + this._signalId = null; + } + } +} + +var SignalManager = class SignalManager { + constructor() { + this._signalsBySource = new Map(); + } + + addSignal(signalSource, signalName, callback) { + let obj = null; + if (signalSource && signalName && callback) { + obj = new Signal(signalSource, signalName, callback); + obj.connect(); + + if (!this._signalsBySource.has(signalSource)) { + this._signalsBySource.set(signalSource, []); + } + this._signalsBySource.get(signalSource).push(obj) + //_log(this._signalsBySource.get(signalSource).length + "Signal length"); + } + return obj; + } + + disconnectAll() { + this._signalsBySource.forEach(signals => this._disconnectSignals(signals)); + } + + disconnectBySource(signalSource) { + if (this._signalsBySource.has(signalSource)) { + this._disconnectSignals(this._signalsBySource.get(signalSource)); + } + } + + _disconnectSignals(signals) { + while (signals.length) { + var signal = signals.shift(); + signal.disconnect(); + signal = null; + } + } +} + + +function getProfilesForPort(portName, card) { + if (card.ports) { + let port = card.ports.find(port => (portName === port.name)); + if (port) { + if (port.profiles) { + return card.profiles.filter(profile => ( + profile.name.indexOf("+input:") == -1 + && profile.available === 1 + && port.profiles.includes(profile.name) + )); + } + } + } + return null; +} + +function setLog(value) { + DEBUG = value; +} + +function _log(msg) { + if (DEBUG == true) { + // global.log("SDC Debug: " + msg); + logWrap("SDC Debug: " + msg); + } +} + +function dump(obj) { + var propValue; + for (var propName in obj) { + try { + propValue = obj[propName]; + _log(propName + "=" + propValue); + } + catch (e) { _log(propName + "!!!Error!!!"); } + } +} + +function getActor(item) { + //.actor is needed for backward compatablity + return (item.actor) ? item.actor : item; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/extension.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/extension.js new file mode 100644 index 0000000..d358025 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/extension.js @@ -0,0 +1,290 @@ +/******************************************************************************* + * 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 . + * ***************************************************************************** + * Original Author: Gopi Sankar Karmegam + ******************************************************************************/ +/* jshint moz:true */ + +const { GObject } = imports.gi; +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const Base = Me.imports.base; +const Lib = Me.imports.convenience; +const _d = Lib._log; +const _dump = Lib.dump; +const getActor = Lib.getActor; +const SignalManager = Lib.SignalManager; +const Prefs = Me.imports.prefs; +const Main = imports.ui.main; +const PopupMenu = imports.ui.popupMenu; + +var SoundOutputDeviceChooser = class SoundOutputDeviceChooser + extends Base.SoundDeviceChooserBase { + constructor() { + super("output"); + } + lookupDeviceById(control, id) { + return control.lookup_output_id(id); + } + changeDevice(control, uidevice) { + control.change_output(uidevice); + } + getDefaultStream(control) { + return control.get_default_sink(); + } + getDefaultIcon() { + return "audio-card"; + } +}; + +var SoundInputDeviceChooser = class SoundInputDeviceChooser + extends Base.SoundDeviceChooserBase { + constructor() { + super("input"); + } + lookupDeviceById(control, id) { + return control.lookup_input_id(id); + } + changeDevice(control, uidevice) { + control.change_input(uidevice); + } + getDefaultStream(control) { + return control.get_default_source(); + } + getDefaultIcon() { + return "audio-input-microphone"; + } +}; + +var VolumeMenuInstance = class VolumeMenuInstance { + constructor(volumeMenu, settings) { + this._settings = settings; + + this._volumeMenu = volumeMenu; + this._input = this._volumeMenu._input; + + this._overrideFunctions(); + this._setSliderVisiblity(); + + this._signalManager = new SignalManager(); + this._signalManager.addSignal(this._settings, "changed::" + + Prefs.SHOW_INPUT_SLIDER, this._setSliderVisiblity.bind(this)); + } + _overrideFunctions() { + // Fix the indicator when using SHOW_INPUT_SLIDER. + // If not applied when SHOW_INPUT_SLIDER=True indication of mic being used will be on (even when not used) + this._volumeMenu._getInputVisibleOriginal = this._volumeMenu.getInputVisible; + this._volumeMenu._getInputVisibleCustom = function() { + return this._input._stream != null && this._input._showInput; + }; + this._volumeMenu.getInputVisible = this._volumeMenu._getInputVisibleCustom; + + this._input._updateVisibilityOriginal = this._input._updateVisibility; + this._input._updateVisibilityCustom = function() { + let old_state_visible = getActor(this.item).visible; + let visible = this._shouldBeVisible(); + + if (old_state_visible != visible) { + getActor(this.item).visible = visible; + } else { + getActor(this.item).notify('visible'); + } + }; + this._input._updateVisibility = this._input._updateVisibilityCustom; + + // Makes slider visible when SHOW_INPUT_SLIDER=True + this._input._showInputSlider = this._settings.get_boolean(Prefs.SHOW_INPUT_SLIDER); + this._input._shouldBeVisibleOriginal = this._input._shouldBeVisible; + this._input._shouldBeVisibleCustom = function() { + return this._showInputSlider && (this._stream != null) || this._shouldBeVisibleOriginal(); + }; + this._input._shouldBeVisible = this._input._shouldBeVisibleCustom; + } + _setSliderVisiblity() { + this._input._showInputSlider = this._settings.get_boolean(Prefs.SHOW_INPUT_SLIDER); + this._input._maybeShowInput(); + } + destroy() { + this._signalManager.disconnectAll(); + delete this._signalManager; + this._volumeMenu.getInputVisible = this._volumeMenu._getInputVisibleOriginal; + this._input._updateVisibility = this._input._updateVisibilityOriginal; + this._input._shouldBeVisible = this._input._shouldBeVisibleOriginal; + + this._input._maybeShowInput(); + + delete this._volumeMenu['_getInputVisibleOriginal']; + delete this._volumeMenu['_getInputVisibleCustom']; + delete this._input['_updateVisibilityOriginal']; + delete this._input['_updateVisibilityCustom']; + delete this._input['_shouldBeVisibleOriginal']; + delete this._input['_shouldBeVisibleCustom']; + delete this._input['_showInputSlider']; // variable + } +} + +var SDCInstance = class SDCInstance { + constructor() { + } + + enable() { + this._settings = ExtensionUtils.getSettings(); + this._signalManager = new SignalManager(); + this._aggregateMenu = Main.panel.statusArea.aggregateMenu; + this._volume = this._aggregateMenu._volume; + this._volumeMenu = this._volume._volumeMenu; + this._aggregateLayout = this._aggregateMenu.menu.box.get_layout_manager(); + let theme = imports.gi.Gtk.IconTheme.get_default(); + if (theme != null) { + let iconPath = Me.dir.get_child('icons'); + if (iconPath != null && iconPath.query_exists(null)) { + theme.append_search_path(iconPath.get_path()); + } + } + + if (this._outputInstance == null) { + this._outputInstance = new SoundOutputDeviceChooser(); + } + if (this._inputInstance == null) { + this._inputInstance = new SoundInputDeviceChooser(); + } + + if (this._volumeMenuInstance == null) { + this._volumeMenuInstance = new VolumeMenuInstance(this._volumeMenu, this._settings); + } + + this._addMenuItem(this._volumeMenu, this._volumeMenu._output.item, this._outputInstance.menuItem); + this._addMenuItem(this._volumeMenu, this._volumeMenu._input.item, this._inputInstance.menuItem); + this._expandVolMenu(); + + this._signalManager.addSignal(this._settings, "changed::" + Prefs.EXPAND_VOL_MENU, this._expandVolMenu.bind(this)); + this._signalManager.addSignal(this._settings, "changed::" + Prefs.INTEGRATE_WITH_SLIDER, this._switchSubmenuMenu.bind(this)); + this._signalManager.addSignal(this._outputInstance, "update-visibility", this._updateMenuVisibility.bind(this)); + this._signalManager.addSignal(this._inputInstance, "update-visibility", this._updateMenuVisibility.bind(this)); + + //If slider disappears remove menu integration, getting complicated!! + this._signalManager.addSignal(getActor(this._volumeMenu._output.item), + "notify::visible", () => { this._updateMenuVisibility(this._outputInstance, false) }); + this._signalManager.addSignal(getActor(this._volumeMenu._input.item), + "notify::visible", () => { this._updateMenuVisibility(this._inputInstance, false) }); + } + + _addMenuItem(_volumeMenu, checkItem, menuItem) { + let menuItems = _volumeMenu._getMenuItems(); + let i = menuItems.findIndex(elem => elem === checkItem); + if (i < 0) { + i = menuItems.length; + } + _volumeMenu.addMenuItem(menuItem, ++i); + this._integrateMenu(_volumeMenu, getActor(checkItem), getActor(menuItem)); + } + + _expandVolMenu() { + if (this._settings.get_boolean(Prefs.EXPAND_VOL_MENU)) { + this._aggregateLayout.addSizeChild(getActor(this._volumeMenu)); + } else { + this._revertVolMenuChanges(); + } + } + + _revertVolMenuChanges() { + this._aggregateLayout._sizeChildren = this._aggregateLayout._sizeChildren.filter(item => item !== getActor(this._volumeMenu)); + this._aggregateLayout.layout_changed(); + } + + _updateMenuVisibility(menuInstance, visible) { + if (menuInstance instanceof SoundOutputDeviceChooser) { + this._integrateMenu(this._volumeMenu, getActor(this._volumeMenu._output.item), getActor(menuInstance.menuItem), visible); + } else { + this._integrateMenu(this._volumeMenu, getActor(this._volumeMenu._input.item), getActor(menuInstance.menuItem), visible); + } + } + + _switchSubmenuMenu() { + _d("Output Device visibility"); + this._updateMenuVisibility(this._outputInstance, getActor(this._outputInstance.menuItem).visible); + _d("Input Device visibility"); + this._updateMenuVisibility(this._inputInstance, getActor(this._inputInstance.menuItem).visible); + } + + _integrateMenu(_volumeMenu, sliderItem, selectorItem, visible) { + let canIntegrate = sliderItem.visible && (visible || selectorItem.visible) && this._settings.get_boolean(Prefs.INTEGRATE_WITH_SLIDER); + if (canIntegrate == true) { + _d("Integrating with Volume menu "); + if (_volumeMenu.box.contains(sliderItem) == true) { + _volumeMenu.box.remove_child(sliderItem); + } + sliderItem.set_x_expand(true); + sliderItem.set_style('padding-right: 0px;'); + if(sliderItem._ornamentLabel) + { + sliderItem._ornamentLabel.hide(); + } + sliderItem.set_track_hover(false); + selectorItem.insert_child_above(sliderItem, selectorItem.label); + selectorItem.label.hide(); + sliderItem.get_next_sibling().hide(); //expander + selectorItem.icon.hide(); + selectorItem.set_style('padding-left: 0px;padding-top: 0px; padding-bottom: 0px'); + } else { + _d("Not integrating with Volume menu") + if (selectorItem.contains(sliderItem) == true) { + selectorItem.remove_child(sliderItem); + } + sliderItem.set_x_expand(false); + sliderItem.set_style(''); + if(sliderItem._ornamentLabel) + { + sliderItem._ornamentLabel.show(); + } + sliderItem.set_track_hover(true); + selectorItem.label.show(); + selectorItem.label.get_next_sibling().show(); //expander + selectorItem.icon.show(); + selectorItem.set_style(''); + if (_volumeMenu.box.contains(sliderItem) == false) { + let oriVisible = sliderItem.visible; + _volumeMenu.box.insert_child_below(sliderItem, selectorItem); + sliderItem.visible = oriVisible; + } + } + } + + disable() { + //this._switchSubmenuMenu(); + this._revertVolMenuChanges(); + if (this._outputInstance) { + this._outputInstance.setVisible(false); + this._outputInstance.destroy(); + this._outputInstance = null; + } + if (this._inputInstance) { + this._inputInstance.setVisible(false); + this._inputInstance.destroy(); + this._inputInstance = null; + } + if (this._volumeMenuInstance) { + this._volumeMenuInstance.destroy(); + this._volumeMenuInstance = null; + } + this._settings = null; + this._signalManager.disconnectAll(); + this._signalManager = null; + } +}; + +function init() { + ExtensionUtils.initTranslations(Me.metadata["gettext-domain"]); + return new SDCInstance(); +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/icons/blank.png b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/icons/blank.png new file mode 100644 index 0000000..23568c6 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/icons/blank.png differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/license b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/license new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/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. + + + Copyright (C) + + 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) + 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/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/de_DE/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/de_DE/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..4929de7 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/de_DE/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/it_IT/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/it_IT/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..63937ad Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/it_IT/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ko/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ko/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..570937d Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ko/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/nl/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/nl/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..bd5188e Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/nl/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_BR/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_BR/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..2a27c47 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_BR/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_PT/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_PT/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..4b47f43 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/pt_PT/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sk/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sk/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..9c773a6 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sk/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sv/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sv/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..2bb16f2 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/sv/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ta/LC_MESSAGES/sound-output-device-chooser.mo b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ta/LC_MESSAGES/sound-output-device-chooser.mo new file mode 100644 index 0000000..d3809ee Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/locale/ta/LC_MESSAGES/sound-output-device-chooser.mo differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/metadata.json b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/metadata.json new file mode 100644 index 0000000..e5c1fae --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/metadata.json @@ -0,0 +1,20 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Shows a list of sound output and input devices (similar to gnome sound settings) in the status menu below the volume slider. Various active ports like HDMI , Speakers etc. of the same device are also displayed for selection. V20+ needs python as dependency. If you want to continue with the old method without Python, use options to switch off New Port identification. But it works with only English", + "gettext-domain": "sound-output-device-chooser", + "name": "Sound Input & Output Device Chooser", + "original-author": "GopI", + "settings-schema": "org.gnome.shell.extensions.sound-output-device-chooser", + "shell-version": [ + "3.34", + "3.32", + "3.36", + "3.38", + "40", + "41", + "42" + ], + "url": "https://github.com/kgshank/gse-sound-output-device-chooser", + "uuid": "sound-output-device-chooser@kgshank.net", + "version": 43 +} \ No newline at end of file diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/prefs.js b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/prefs.js new file mode 100644 index 0000000..38093b0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/prefs.js @@ -0,0 +1,328 @@ +/******************************************************************************* + * 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 . + * + * Original Author: Gopi Sankar Karmegam + ******************************************************************************/ +/* jshint moz:true */ + +const { Gio, GObject, Gtk } = imports.gi; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); +const Lib = Me.imports.convenience; +const _d = Lib._log; +const SignalManager = Lib.SignalManager; + +const Gettext = imports.gettext; +const _ = Gettext.gettext; + +var HIDE_ON_SINGLE_DEVICE = "hide-on-single-device"; +var HIDE_MENU_ICONS = "hide-menu-icons"; +var SHOW_PROFILES = "show-profiles"; +var PORT_SETTINGS = "ports-settings"; +var SHOW_INPUT_SLIDER = "show-input-slider"; +var SHOW_INPUT_DEVICES = "show-input-devices"; +var SHOW_OUTPUT_DEVICES = "show-output-devices"; +var ENABLE_LOG = "enable-log"; +var NEW_PROFILE_ID_DEPRECATED = "new-profile-indentification"; +var NEW_PROFILE_ID = "new-profile-identification"; +var EXPAND_VOL_MENU = "expand-volume-menu"; +var CANNOT_ACTIVATE_HIDDEN_DEVICE = "cannot-activate-hidden-device"; +var OMIT_DEVICE_ORIGIN = "omit-device-origins"; +var INTEGRATE_WITH_SLIDER = "integrate-with-slider"; + +var ICON_THEME = "icon-theme"; +var ICON_THEME_COLORED = "colored"; +var ICON_THEME_MONOCHROME = "monochrome"; +var ICON_THEME_NONE = "none"; + +var DISPLAY_OPTIONS = { SHOW_ALWAYS: 1, HIDE_ALWAYS: 2, DEFAULT: 3, INITIAL: -1 }; + +const PORT_SETTINGS_VERSION = 3; + +function init() { + ExtensionUtils.initTranslations(); +} + +function getPortsFromSettings(_settings) { + //_d(_settings.get_string(PORT_SETTINGS)); + let obj = JSON.parse(_settings.get_string(PORT_SETTINGS)); + let currentSettingsVersion = PORT_SETTINGS_VERSION; + if (Array.isArray(obj)) { + currentSettingsVersion = 1; + } + else { + currentSettingsVersion = obj.version; + } + + if (currentSettingsVersion < PORT_SETTINGS_VERSION) { + obj = migratePortSettings(currentSettingsVersion, obj, _settings); + } + return obj.ports; +} + +function setPortsSettings(ports, _settings) { + let settingsObj = { "version": PORT_SETTINGS_VERSION }; + settingsObj.ports = ports; + //_d(JSON.stringify(settingsObj)); + _settings.set_string(PORT_SETTINGS, JSON.stringify(settingsObj)); + return settingsObj; +} + +function getPortDisplayName(port) { + return `${port.human_name} - ${port.card_description}`; +} + +function migratePortSettings(currVersion, currSettings, _settings) { + let ports = []; + let _lPorts = Lib.getPorts(true).slice(); + switch (currVersion) { + case 1: + for (let port of currSettings) { + for (var i = 0; i < _lPorts.length; i++) { + let _lPort = _lPorts[i]; + if (port.human_name == _lPort.human_name && port.name == _lPort.name) { + port.card_name = _lPort.card_name; + port.card_description = _lPort.card_description; + port.display_name = getPortDisplayName(_lPort); + _lPorts.splice(i, 1); + ports.push(port); + break; + } + } + } + break; + + case 2: + for (let port of currSettings.ports) { + for (var i = 0; i < _lPorts.length; i++) { + let _lPort = _lPorts[i]; + if (port.human_name == _lPort.human_name && port.name == _lPort.name && port.card_name == _lPort.card_name) { + port.card_description = _lPort.card_description; + _lPorts.splice(i, 1); + ports.push(port); + break; + } + } + } + break; + } + return setPortsSettings(ports, _settings); +} + +const SDCSettingsWidget = new GObject.Class({ + Name: "SDC.Prefs.Widget", + GTypeName: "SDCSettingsWidget", + Extends: Gtk.Box, + + _init: function(params) { + this.parent(params); + this.orientation = Gtk.Orientation.VERTICAL; + this.spacing = 0; + let uiFileSuffix = ""; + + if (Gtk.get_major_version() >= "4") { + uiFileSuffix = "40"; + this.__addFn = this.append; + this.__showFn = this.show; + } + else { + this.__addFn = x => this.pack_start(x, true, true, 0); + this.__showFn = this.show_all; + } + // creates the settings + this._settings = ExtensionUtils.getSettings(); + + Lib.setLog(this._settings.get_boolean(ENABLE_LOG)); + + // creates the ui builder and add the main resource file + let uiFilePath = Me.path + "/ui/prefs-dialog" + uiFileSuffix + ".glade"; + let builder = new Gtk.Builder(); + builder.set_translation_domain("sound-output-device-chooser"); + + if (builder.add_from_file(uiFilePath) == 0) { + _d("JS LOG: could not load the ui file: %s".format(uiFilePath)); + let label = new Gtk.Label({ + label: _("Could not load the preferences UI file"), + vexpand: true + }); + this.__addFn(label); + } else { + _d("JS LOG:_UI file receive and load: " + uiFilePath); + + let mainContainer = builder.get_object("main-container"); + + this.__addFn(mainContainer); + + this._signalManager = new SignalManager(); + + let showProfileSwitch = builder.get_object(SHOW_PROFILES); + let volMenuSwitch = builder.get_object(EXPAND_VOL_MENU); + let singleDeviceSwitch = builder.get_object(HIDE_ON_SINGLE_DEVICE); + let showInputSliderSwitch = builder.get_object(SHOW_INPUT_SLIDER); + let showInputDevicesSwitch = builder.get_object(SHOW_INPUT_DEVICES); + let showOutputDevicesSwitch = builder.get_object(SHOW_OUTPUT_DEVICES); + let hideMenuIconsSwitch = builder.get_object(HIDE_MENU_ICONS); + let iconThemeCombo = builder.get_object(ICON_THEME); + let logSwitch = builder.get_object(ENABLE_LOG); + let newProfileIdSwitch = builder.get_object(NEW_PROFILE_ID); + let cantActHiddSwitch = builder.get_object(CANNOT_ACTIVATE_HIDDEN_DEVICE); + let omitDeviceOrigin = builder.get_object(OMIT_DEVICE_ORIGIN); + let integrateWithSlider = builder.get_object(INTEGRATE_WITH_SLIDER); + + this._settings.bind(HIDE_ON_SINGLE_DEVICE, singleDeviceSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(SHOW_PROFILES, showProfileSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(EXPAND_VOL_MENU, volMenuSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(SHOW_INPUT_SLIDER, showInputSliderSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(SHOW_INPUT_DEVICES, showInputDevicesSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(SHOW_OUTPUT_DEVICES, showOutputDevicesSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(HIDE_MENU_ICONS, hideMenuIconsSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(ENABLE_LOG, logSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(NEW_PROFILE_ID, newProfileIdSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(CANNOT_ACTIVATE_HIDDEN_DEVICE, cantActHiddSwitch, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(OMIT_DEVICE_ORIGIN, omitDeviceOrigin, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(INTEGRATE_WITH_SLIDER, integrateWithSlider, "active", Gio.SettingsBindFlags.DEFAULT); + this._settings.bind(ICON_THEME, iconThemeCombo, "active-id", Gio.SettingsBindFlags.DEFAULT); + + //Show always is not working always, hidden in the UI directly + let showAlwaysToggleRender = builder.get_object("ShowAlwaysToggleRender"); + let hideAlwaysToggleRender = builder.get_object("HideAlwaysToggleRender"); + let showActiveToggleRender = builder.get_object("ShowActiveToggleRender"); + + this._signalManager.addSignal(showAlwaysToggleRender, "toggled", this._showAlwaysToggleRenderCallback.bind(this)); + this._signalManager.addSignal(hideAlwaysToggleRender, "toggled", this._hideAlwaysToggleRenderCallback.bind(this)); + this._signalManager.addSignal(showActiveToggleRender, "toggled", this._showActiveToggleRenderCallback.bind(this)); + + this._portsStore = builder.get_object("ports-store"); + + this._populatePorts(); + this._restorePortsFromSettings(); + } + }, + + _populatePorts: function() { + let ports = Lib.getPorts(true); + ports.sort((a, b) => (b.direction.localeCompare(a.direction)) || getPortDisplayName(a).localeCompare(getPortDisplayName(b))).forEach(port => { + this._portsStore.set(this._portsStore.append(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + [port.human_name, false, false, true, port.name, 3, port.card_name, port.card_description, getPortDisplayName(port), port.direction]); + }); + }, + + _showAlwaysToggleRenderCallback: function(widget, path) { + //this._toggleCallback(widget, path, 1, [2, 3]); + this._toggleCallback(widget, path, DISPLAY_OPTIONS.SHOW_ALWAYS, [2, 3]); + }, + + _hideAlwaysToggleRenderCallback: function(widget, path) { + //this._toggleCallback(widget, path, 2, [1, 3]); + this._toggleCallback(widget, path, DISPLAY_OPTIONS.HIDE_ALWAYS, [1, 3]); + }, + + _showActiveToggleRenderCallback: function(widget, path) { + //this._toggleCallback(widget, path, 3, [1, 2]); + this._toggleCallback(widget, path, DISPLAY_OPTIONS.DEFAULT, [1, 2]); + }, + + _toggleCallback: function(widget, path, activeCol, inactiveCols) { + let active = !widget.active; + if (!active) { + return; + } + let [success, iter] = this._portsStore.get_iter_from_string(path); + if (!success) { + return; + } + /*Dont support non-pci cards for show always*/ + let card_name = this._portsStore.get_value(iter, 6); + if (!/\.pci-/.exec(card_name) && activeCol == 1) { + //this._toggleCallback(widget, path, 3, [1, 2]); + this._toggleCallback(widget, path, DISPLAY_OPTIONS.DEFAULT, [1, 2]); + } + else { + this._portsStore.set_value(iter, activeCol, active); + this._portsStore.set_value(iter, 5, activeCol); + for (let col of inactiveCols) { + this._portsStore.set_value(iter, col, !active); + } + this._commitSettings(); + } + }, + + _commitSettings: function() { + let ports = []; + let [success, iter] = this._portsStore.get_iter_first(); + while (iter && success) { + if (!this._portsStore.get_value(iter, 3)) { + let display_option = this._portsStore.get_value(iter, 5); + //if (display_option != 3) {//Dont store default value + if (display_option != DISPLAY_OPTIONS.DEFAULT) {//Dont store default value + ports.push({ + human_name: this._portsStore.get_value(iter, 0), + name: this._portsStore.get_value(iter, 4), + display_option: display_option, + card_name: this._portsStore.get_value(iter, 6), + card_description: this._portsStore.get_value(iter, 7), + display_name: this._portsStore.get_value(iter, 8) + }); + } + } + success = this._portsStore.iter_next(iter); + } + setPortsSettings(ports, this._settings); + }, + + _restorePortsFromSettings: function() { + let ports = getPortsFromSettings(this._settings); + + let found; + for (let port of ports) { + found = false; + if (!port || !port.human_name || !port.name) { + continue; + } + + let [success, iter] = this._portsStore.get_iter_first(); + + while (iter && success) { + let human_name = this._portsStore.get_value(iter, 0); + let name = this._portsStore.get_value(iter, 4); + let card_name = this._portsStore.get_value(iter, 6); + + if (port.name == name && port.human_name == human_name && port.card_name == card_name) { + this._portsStore.set_value(iter, 3, false); + this._portsStore.set_value(iter, port.display_option, true); + this._portsStore.set_value(iter, 5, port.display_option); + found = true; + break; + } + success = this._portsStore.iter_next(iter); + } + + if (!found) { + iter = this._portsStore.append(); + this._portsStore.set(iter, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + [port.human_name, false, false, false, port.name, port.display_option, port.card_name, port.card_description, port.display_name, ""]); + this._portsStore.set_value(iter, port.display_option, true); + } + } + } +}); + + +function buildPrefsWidget() { + let _settingsWidget = new SDCSettingsWidget(); + _settingsWidget.__showFn(); + + return _settingsWidget; +} diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/gschemas.compiled b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/gschemas.compiled new file mode 100644 index 0000000..7c5c5c1 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/gschemas.compiled differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/org.gnome.shell.extensions.sound-output-device-chooser.gschema.xml b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/org.gnome.shell.extensions.sound-output-device-chooser.gschema.xml new file mode 100644 index 0000000..d34d510 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/schemas/org.gnome.shell.extensions.sound-output-device-chooser.gschema.xml @@ -0,0 +1,101 @@ + + + + + + false + Preference to show the chooser when only one device is available + Value set to false hides the device chooser when only one device is available + + + + true + Preference to show the available profiles for all devices + Value set to true displays the individual available profiles for each device + + + + true + Preference to expand volume menu to fit the name of the sound devices + Value set to true expands the volume menu to fit the names of sound devices displayed in the selector + + + + true + Preference to use monochrome icons instead of default icons + Value set to true uses monochrome icons + + + + true + Preference to show input slider always + Value set to true displays the slider control for input device volume + + + + true + Preference to show input device chooser + Value set to true displays the device chooser for input devices + + + + true + Preference to show output device chooser + Value set to true displays the device chooser for output devices + + + + "{\"version\":3,\"ports\":[]}" + Preference to hide/show different ports always + + + + + "monochrome" + Preference indicating the type of icons used by the extension + Value can be "colored", "monochrome", "none", etc. + + + + false + Preference indicating whether the icons are hidden in the drop-down menu (but are visible in the expanded list). + + + + + false + Preference indicating log messages should be written to console + + + + + true + (Deprecated)Old preference name with a typo. To be removed in the next shell version + + + + + true + Preference to enable python script to identify port profiles + + + + + true + Preference to avoid activation of hidden devices in Port Settings + + + + + false + Preference to omit device origin at Volume Menu + + + + + false + Preference to integrate selector with slider + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog.glade b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog.glade new file mode 100644 index 0000000..b6e62e7 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog.glade @@ -0,0 +1,956 @@ + + + + + + + + + + + + + + monochrome + Monochrome + + + colored + Colored + + + none + None + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + 6 + 6 + vertical + 2 + + + True + False + True + True + True + + + True + False + 12 + 12 + vertical + 12 + + + True + False + 10 + 10 + 0.029999999329447746 + out + + + True + False + none + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Integrate selector with slider + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Hide selector if there's only one device + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Display audio profiles for selection + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Omit device origins at Volume Menu + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Extend Volume Menu to fit device names + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + + + True + False + start + Don't allow device hidden in Port Settings to be activated + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + + + True + False + start + (Select / deselect the required device in the Gnome Sound Settings) + + + True + True + 0 + + + + + + + + + + + True + False + General Settings + + + + + + + + False + True + 0 + + + + + True + False + 10 + 10 + 0.029999999329447746 + out + + + True + False + + + 100 + True + True + + + True + False + center + 6 + 6 + + + True + False + start + Show output devices + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + + + True + False + Output Devices + + + + + + + + False + True + 1 + + + + + True + False + 10 + 10 + 0.029999999329447746 + out + + + True + False + none + + + 100 + True + True + True + + + True + False + center + 6 + 6 + + + True + False + start + Show input devices + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + 100 + True + True + center + + + True + False + 6 + 6 + + + True + False + start + Show volume control for default device + + + True + True + 0 + + + + + True + True + end + + + False + True + 1 + + + + + + + + + + + True + False + Input Devices + + + + + + + + False + True + 2 + + + + + True + False + 10 + 10 + 0.029999999329447746 + in + + + True + False + none + + + 100 + True + True + + + 6 + True + False + 6 + 6 + + + True + False + start + Icon Theme + + + True + True + 0 + + + + + 100 + True + False + icon-theme-store + 0 + + + + 1 + + + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Display icons only in selection list + + + True + True + 0 + + + + + True + True + + + False + True + 1 + + + + + + + + + + + True + False + Icons + + + + + + + + False + True + 3 + + + + + True + False + 10 + 10 + 0.029999999329447746 + in + + + True + False + none + + + 100 + True + True + + + 6 + True + False + 6 + 6 + + + True + False + start + Enable Log messages + + + True + True + 0 + + + + + True + True + + + False + True + 1 + + + + + + + + + 100 + True + True + + + True + False + 6 + 6 + + + True + False + start + Enable new profile identification + + + True + True + 0 + + + + + True + True + True + + + False + True + 1 + + + + + + + + + + + True + False + Miscellaneous + + + + + + + + False + True + 4 + + + + + False + True + 0 + + + + + True + False + 12 + 12 + vertical + + + True + False + 10 + 10 + True + 0.029999999329447746 + out + + + True + False + 4 + True + vertical + + + True + True + 0.9999999986588954 + True + True + queue + in + 500 + + + True + True + True + ports-store + False + both + + + + + + True + autosize + 100 + Name + True + + + + 8 + + + + + + + autosize + 100 + Device Type + True + descending + + + + 9 + + + + + + + False + autosize + Show + + + True + + + 1 + + + + + + + autosize + Hide + + + True + + + 2 + + + + + + + autosize + Default + + + True + + + 3 + + + + + + + + + False + True + 1 + + + + + + + True + False + Port Settings + + + + + + + + False + True + 0 + + + + + False + True + 1 + + + + + False + True + 1 + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog40.glade b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog40.glade new file mode 100644 index 0000000..7e30ccc --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/ui/prefs-dialog40.glade @@ -0,0 +1,655 @@ + + + + + + + + + + + + + monochrome + Monochrome + + + colored + Colored + + + none + None + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 6 + 6 + 6 + 6 + vertical + 2 + + + 0 + 1 + 1 + 1 + + + 12 + 6 + 12 + 12 + vertical + 12 + + + 0 + + + 0 + none + + + 100 + + + 0 + 6 + 6 + + + 1 + start + 5 + Integrate selector with slider + + + + + end + 5 + + + + + + + + + 100 + + + 0 + 6 + 6 + + + 1 + start + 5 + Hide selector if there's only one device + + + + + end + 5 + + + + + + + + + 100 + + + 6 + 6 + + + 1 + start + 5 + Display audio profiles for selection + + + + + end + 5 + + + + + + + + + 100 + + + 6 + 6 + + + 1 + start + 5 + 20 + Omit device origins at Volume Menu + + + + + end + 5 + + + + + + + + + 100 + + + 6 + 6 + + + 1 + start + 5 + 20 + Extend Volume Menu to fit device names + + + + + end + 5 + + + + + + + + + 100 + + + 6 + + + 1 + start + 5 + 20 + Don't allow device hidden in Port Settings to be activated + + + + + end + 5 + + + + + + + + + 100 + + + 6 + + + 1 + start + 5 + 20 + (Select / deselect the required device in the Gnome Sound Settings) + + + + + + + + + + + General Settings + + + + + + + + + + + + + + + 100 + + + center + 6 + 6 + + + 1 + start + 5 + Show output devices + + + + + end + 5 + + + + + + + + + + + + Output Devices + + + + + + + + + + + + + none + + + 100 + 1 + + + center + 6 + 6 + + + 1 + start + 5 + Show input devices + + + + + end + 5 + + + + + + + + + 100 + center + + + 6 + 6 + + + 1 + start + 5 + Show volume control for default device + + + + + end + 5 + + + + + + + + + + + + Input Devices + + + + + + + + + + + + + none + + + 100 + + + 6 + 6 + 6 + + + 1 + start + 5 + Icon Theme + + + + + 100 + 5 + icon-theme-store + 0 + + + + 1 + + + + + + + + + + + 100 + + + 6 + 6 + + + 1 + start + 5 + Display icons only in selection list + + + + + 5 + + + + + + + + + + + + Icons + + + + + + + + + + + + + none + + + 100 + + + 6 + 6 + 6 + + + 1 + start + 5 + Enable Log messages + + + + + + + + + + + + 100 + + + 6 + 6 + + + 1 + start + 5 + Enable new profile identification + + + + + 1 + + + + + + + + > + + + + Miscellaneous + + + + + + + + + + + + 6 + 12 + 12 + 12 + vertical + + + 1 + + + + 4 + 4 + 4 + 1 + vertical + + + 0.9999999986588954 + 1 + 1 + 500 + + + + + 1 + ports-store + + + + + + 1 + autosize + 100 + Name + 1 + descending + + + + 8 + + + + + + + autosize + 100 + Device Type + True + descending + + + + 9 + + + + + + + False + autosize + Show + + + 1 + + + 1 + + + + + + + autosize + Hide + + + 1 + + + 2 + + + + + + + autosize + Default + + + 1 + + + 3 + + + + + + + + + + + + + + + Port Settings + + + + + + + + + + + + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-310.pyc b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-310.pyc new file mode 100644 index 0000000..fc586a5 Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-310.pyc differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-39.pyc b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-39.pyc new file mode 100644 index 0000000..565c6db Binary files /dev/null and b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/__pycache__/libpulse_introspect.cpython-39.pyc differ diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py new file mode 100644 index 0000000..af4209a --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/libpulse_introspect.py @@ -0,0 +1,544 @@ +# This file is generated using clang2py script. The following files are used +# '/usr/include/pulse/introspect.h' '/usr/include/pulse/mainloop.h' '/usr/include/pulse/context.h' +# Refer additional licensing requirements for the files included +# sample commands used +# python3 /usr/bin/clang2py --clang-args="-I/usr/include/clang/6.0/include -I/usr/include/pulse" -l /usr/lib/libpulse.so '/usr/include/pulse/introspect.h' '/usr/include/pulse/mainloop.h' '/usr/include/pulse/proplist.h' +# python3 /usr/local/bin/clang2py --clang-args="-I/usr/include/clang/6.0/include -I/usr/include/pulse" -l /usr/lib/x86_64-linux-gnu/libpulse.so '/usr/include/pulse/introspect.h' '/usr/include/pulse/mainloop.h' +# python3 /usr/local/bin/clang2py --clang-args="-I/usr/include/clang/6.0/include -I/usr/include/pulse" -l /usr/lib/x86_64-linux-gnu/libpulse.so '/usr/include/pulse/context.h' +################################################################################ +# # 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 . +# # +# # Original Author: Gopi Sankar Karmegam +# ############################################################################## +# -#- coding: utf-8 -#- +# +# TARGET arch is: ['-I/usr/include/clang/6.0/include', '-I/usr/include/pulse'] +# WORD_SIZE is: 8 +# POINTER_SIZE is: 8 +# LONGDOUBLE_SIZE is: 16 +# + +# Updated to determine libpulse.so location +import ctypes +from ctypes.util import find_library + +c_int128 = ctypes.c_ubyte*16 +c_uint128 = c_int128 +void = None +if ctypes.sizeof(ctypes.c_longdouble) == 16: + c_long_double_t = ctypes.c_longdouble +else: + c_long_double_t = ctypes.c_ubyte*16 + +# if local wordsize is same as target, keep ctypes pointer function. +if ctypes.sizeof(ctypes.c_void_p) == 8: + POINTER_T = ctypes.POINTER +else: + # required to access _ctypes + import _ctypes + # Emulate a pointer class using the approriate c_int32/c_int64 type + # The new class should have : + # ['__module__', 'from_param', '_type_', '__dict__', '__weakref__', '__doc__'] + # but the class should be submitted to a unique instance for each base type + # to that if A == B, POINTER_T(A) == POINTER_T(B) + ctypes._pointer_t_type_cache = {} + def POINTER_T(pointee): + # a pointer should have the same length as LONG + fake_ptr_base_type = ctypes.c_uint64 + # specific case for c_void_p + if pointee is None: # VOID pointer type. c_void_p. + pointee = type(None) # ctypes.c_void_p # ctypes.c_ulong + clsname = 'c_void' + else: + clsname = pointee.__name__ + if clsname in ctypes._pointer_t_type_cache: + return ctypes._pointer_t_type_cache[clsname] + # make template + class _T(_ctypes._SimpleCData,): + _type_ = 'L' + _subtype_ = pointee + def _sub_addr_(self): + return self.value + def __repr__(self): + return '%s(%d)'%(clsname, self.value) + def contents(self): + raise TypeError('This is not a ctypes pointer.') + def __init__(self, **args): + raise TypeError('This is not a ctypes pointer. It is not instanciable.') + _class = type('LP_%d_%s'%(8, clsname), (_T,),{}) + ctypes._pointer_t_type_cache[clsname] = _class + return _class + +_libraries = {} + +libpulse_library_name = find_library('pulse') +if libpulse_library_name is None: + raise Exception('No libpulse.so library found!') + +try: + _libraries['libpulse.so'] = ctypes.cdll.LoadLibrary(libpulse_library_name) +except OSError: + raise Exception('Cannot load libpulse.so library!') + + +uint32_t = ctypes.c_uint32 + +size_t = ctypes.c_uint64 +class struct_pa_context(ctypes.Structure): + pass + +pa_context = struct_pa_context +pa_context_notify_cb_t = ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_context), POINTER_T(None)) +pa_context_success_cb_t = POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_context), ctypes.c_int32, POINTER_T(None))) + +class struct_pa_proplist(ctypes.Structure): + pass + +pa_context_event_cb_t = POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_context), ctypes.c_char_p, POINTER_T(struct_pa_proplist), POINTER_T(None))) +class struct_pa_mainloop_api(ctypes.Structure): + pass + +pa_context_new = _libraries['libpulse.so'] .pa_context_new +pa_context_new.restype = POINTER_T(struct_pa_context) +pa_context_new.argtypes = [POINTER_T(struct_pa_mainloop_api), ctypes.c_char_p] + +# pa_context_new_with_proplist = _libraries['libpulse.so'] .pa_context_new_with_proplist +# pa_context_new_with_proplist.restype = POINTER_T(struct_pa_context) +# pa_context_new_with_proplist.argtypes = [POINTER_T(struct_pa_mainloop_api), ctypes.c_char_p, POINTER_T(struct_pa_proplist)] + +pa_context_unref = _libraries['libpulse.so'] .pa_context_unref +pa_context_unref.restype = None +pa_context_unref.argtypes = [POINTER_T(struct_pa_context)] + +# pa_context_ref = _libraries['libpulse.so'] .pa_context_ref +# pa_context_ref.restype = POINTER_T(struct_pa_context) +# pa_context_ref.argtypes = [POINTER_T(struct_pa_context)] + +pa_context_set_state_callback = _libraries['libpulse.so'] .pa_context_set_state_callback +pa_context_set_state_callback.restype = None +pa_context_set_state_callback.argtypes = [POINTER_T(struct_pa_context), pa_context_notify_cb_t, POINTER_T(None)] +# +# pa_context_set_event_callback = _libraries['libpulse.so'] .pa_context_set_event_callback +# pa_context_set_event_callback.restype = None +# pa_context_set_event_callback.argtypes = [POINTER_T(struct_pa_context), pa_context_event_cb_t, POINTER_T(None)] +# +# pa_context_errno = _libraries['libpulse.so'] .pa_context_errno +# pa_context_errno.restype = ctypes.c_int32 +# pa_context_errno.argtypes = [POINTER_T(struct_pa_context)] +# +# pa_context_is_pending = _libraries['libpulse.so'] .pa_context_is_pending +# pa_context_is_pending.restype = ctypes.c_int32 +# pa_context_is_pending.argtypes = [POINTER_T(struct_pa_context)] + + + +# values for enumeration 'pa_context_state' +pa_context_state__enumvalues = { + 0: 'PA_CONTEXT_UNCONNECTED', + 1: 'PA_CONTEXT_CONNECTING', + 2: 'PA_CONTEXT_AUTHORIZING', + 3: 'PA_CONTEXT_SETTING_NAME', + 4: 'PA_CONTEXT_READY', + 5: 'PA_CONTEXT_FAILED', + 6: 'PA_CONTEXT_TERMINATED', +} + +PA_CONTEXT_UNCONNECTED = 0 +PA_CONTEXT_CONNECTING = 1 +PA_CONTEXT_AUTHORIZING = 2 +PA_CONTEXT_SETTING_NAME = 3 +PA_CONTEXT_READY = 4 +PA_CONTEXT_FAILED = 5 +PA_CONTEXT_TERMINATED = 6 + +pa_context_state = ctypes.c_int # enum +pa_context_state_t = pa_context_state +pa_context_state_t__enumvalues = pa_context_state__enumvalues + +pa_context_get_state = _libraries['libpulse.so'] .pa_context_get_state +pa_context_get_state.restype = pa_context_state_t +pa_context_get_state.argtypes = [POINTER_T(struct_pa_context)] + +# values for enumeration 'pa_context_flags' +pa_context_flags__enumvalues = { + 0: 'PA_CONTEXT_NOFLAGS', + 1: 'PA_CONTEXT_NOAUTOSPAWN', + 2: 'PA_CONTEXT_NOFAIL', +} +PA_CONTEXT_NOFLAGS = 0 +PA_CONTEXT_NOAUTOSPAWN = 1 +PA_CONTEXT_NOFAIL = 2 +pa_context_flags = ctypes.c_int # enum +pa_context_flags_t = pa_context_flags +pa_context_flags_t__enumvalues = pa_context_flags__enumvalues +class struct_pa_spawn_api(ctypes.Structure): + pass + +pa_context_connect = _libraries['libpulse.so'] .pa_context_connect +pa_context_connect.restype = ctypes.c_int32 +pa_context_connect.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p, pa_context_flags_t, POINTER_T(struct_pa_spawn_api)] +pa_context_disconnect = _libraries['libpulse.so'] .pa_context_disconnect +pa_context_disconnect.restype = None +pa_context_disconnect.argtypes = [POINTER_T(struct_pa_context)] + +class struct_pa_operation(ctypes.Structure): + pass + +# pa_context_drain = _libraries['libpulse.so'] .pa_context_drain +# pa_context_drain.restype = POINTER_T(struct_pa_operation) +# pa_context_drain.argtypes = [POINTER_T(struct_pa_context), pa_context_notify_cb_t, POINTER_T(None)] +# pa_context_exit_daemon = _libraries['libpulse.so'] .pa_context_exit_daemon +# pa_context_exit_daemon.restype = POINTER_T(struct_pa_operation) +# pa_context_exit_daemon.argtypes = [POINTER_T(struct_pa_context), pa_context_success_cb_t, POINTER_T(None)] +# pa_context_set_default_sink = _libraries['libpulse.so'] .pa_context_set_default_sink +# pa_context_set_default_sink.restype = POINTER_T(struct_pa_operation) +# pa_context_set_default_sink.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p, pa_context_success_cb_t, POINTER_T(None)] +# pa_context_set_default_source = _libraries['libpulse.so'] .pa_context_set_default_source +# pa_context_set_default_source.restype = POINTER_T(struct_pa_operation) +# pa_context_set_default_source.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p, pa_context_success_cb_t, POINTER_T(None)] +# pa_context_is_local = _libraries['libpulse.so'] .pa_context_is_local +# pa_context_is_local.restype = ctypes.c_int32 +# pa_context_is_local.argtypes = [POINTER_T(struct_pa_context)] +# pa_context_set_name = _libraries['libpulse.so'] .pa_context_set_name +# pa_context_set_name.restype = POINTER_T(struct_pa_operation) +# pa_context_set_name.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p, pa_context_success_cb_t, POINTER_T(None)] +# pa_context_get_server = _libraries['libpulse.so'] .pa_context_get_server +# pa_context_get_server.restype = ctypes.c_char_p +# pa_context_get_server.argtypes = [POINTER_T(struct_pa_context)] + +# pa_context_get_protocol_version = _libraries['libpulse.so'] .pa_context_get_protocol_version +# pa_context_get_protocol_version.restype = uint32_t +# pa_context_get_protocol_version.argtypes = [POINTER_T(struct_pa_context)] +# pa_context_get_server_protocol_version = _libraries['libpulse.so'] .pa_context_get_server_protocol_version +# pa_context_get_server_protocol_version.restype = uint32_t +# pa_context_get_server_protocol_version.argtypes = [POINTER_T(struct_pa_context)] +class struct_pa_card_profile_info(ctypes.Structure): + _pack_ = True # source:False + _fields_ = [ + ('name', ctypes.c_char_p), + ('description', ctypes.c_char_p), + ('n_sinks', ctypes.c_uint32), + ('n_sources', ctypes.c_uint32), + ('priority', ctypes.c_uint32), + ('PADDING_0', ctypes.c_ubyte * 4), + ] + +pa_card_profile_info = struct_pa_card_profile_info +class struct_pa_card_profile_info2(ctypes.Structure): + _pack_ = True # source:False + _fields_ = [ + ('name', ctypes.c_char_p), + ('description', ctypes.c_char_p), + ('n_sinks', ctypes.c_uint32), + ('n_sources', ctypes.c_uint32), + ('priority', ctypes.c_uint32), + ('available', ctypes.c_int32), + ] + +pa_card_profile_info2 = struct_pa_card_profile_info2 +class struct_pa_card_port_info(ctypes.Structure): + _pack_ = True # source:False + _fields_ = [ + ('name', ctypes.c_char_p), + ('description', ctypes.c_char_p), + ('priority', ctypes.c_uint32), + ('available', ctypes.c_int32), + ('direction', ctypes.c_int32), + ('n_profiles', ctypes.c_uint32), + ('profiles', POINTER_T(POINTER_T(struct_pa_card_profile_info))), + ('proplist', POINTER_T(struct_pa_proplist)), + ('latency_offset', ctypes.c_int64), + ('profiles2', POINTER_T(POINTER_T(struct_pa_card_profile_info2))), + ] + +pa_card_port_info = struct_pa_card_port_info +class struct_pa_card_info(ctypes.Structure): + _pack_ = True # source:False + _fields_ = [ + ('index', ctypes.c_uint32), + ('PADDING_0', ctypes.c_ubyte * 4), + ('name', ctypes.c_char_p), + ('owner_module', ctypes.c_uint32), + ('PADDING_1', ctypes.c_ubyte * 4), + ('driver', ctypes.c_char_p), + ('n_profiles', ctypes.c_uint32), + ('PADDING_2', ctypes.c_ubyte * 4), + ('profiles', POINTER_T(struct_pa_card_profile_info)), + ('active_profile', POINTER_T(struct_pa_card_profile_info)), + ('proplist', POINTER_T(struct_pa_proplist)), + ('n_ports', ctypes.c_uint32), + ('PADDING_3', ctypes.c_ubyte * 4), + ('ports', POINTER_T(POINTER_T(struct_pa_card_port_info))), + ('profiles2', POINTER_T(POINTER_T(struct_pa_card_profile_info2))), + ('active_profile2', POINTER_T(struct_pa_card_profile_info2)), + ] + +pa_card_info = struct_pa_card_info +pa_card_info_cb_t = ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_context), POINTER_T(struct_pa_card_info), ctypes.c_int32, POINTER_T(None)) +pa_context_get_card_info_by_index = _libraries['libpulse.so'].pa_context_get_card_info_by_index +pa_context_get_card_info_by_index.restype = POINTER_T(struct_pa_operation) +pa_context_get_card_info_by_index.argtypes = [POINTER_T(struct_pa_context), uint32_t, pa_card_info_cb_t, POINTER_T(None)] + + +pa_context_get_card_info_list = _libraries['libpulse.so'].pa_context_get_card_info_list +pa_context_get_card_info_list.restype = POINTER_T(struct_pa_operation) +pa_context_get_card_info_list.argtypes = [POINTER_T(struct_pa_context), pa_card_info_cb_t, POINTER_T(None)] + + +# values for enumeration 'pa_update_mode' +# pa_update_mode__enumvalues = { +# 0: 'PA_UPDATE_SET', +# 1: 'PA_UPDATE_MERGE', +# 2: 'PA_UPDATE_REPLACE', +# } +# PA_UPDATE_SET = 0 +# PA_UPDATE_MERGE = 1 +# PA_UPDATE_REPLACE = 2 +# pa_update_mode = ctypes.c_int # enum +# pa_update_mode_t = pa_update_mode +# pa_update_mode_t__enumvalues = pa_update_mode__enumvalues +# pa_context_proplist_update = _libraries['libpulse.so'] .pa_context_proplist_update +# pa_context_proplist_update.restype = POINTER_T(struct_pa_operation) +# pa_context_proplist_update.argtypes = [POINTER_T(struct_pa_context), pa_update_mode_t, POINTER_T(struct_pa_proplist), pa_context_success_cb_t, POINTER_T(None)] +# pa_context_proplist_remove = _libraries['libpulse.so'] .pa_context_proplist_remove +# pa_context_proplist_remove.restype = POINTER_T(struct_pa_operation) +# pa_context_proplist_remove.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p * 0, pa_context_success_cb_t, POINTER_T(None)] +# pa_context_get_index = _libraries['libpulse.so'] .pa_context_get_index +# pa_context_get_index.restype = uint32_t +# pa_context_get_index.argtypes = [POINTER_T(struct_pa_context)] +class struct_pa_time_event(ctypes.Structure): + pass + +# pa_usec_t = ctypes.c_uint64 +class struct_timeval(ctypes.Structure): + pass +# +# pa_time_event_cb_t = POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_time_event), POINTER_T(struct_timeval), POINTER_T(None))) +# pa_context_rttime_new = _libraries['libpulse.so'] .pa_context_rttime_new +# pa_context_rttime_new.restype = POINTER_T(struct_pa_time_event) +# pa_context_rttime_new.argtypes = [POINTER_T(struct_pa_context), pa_usec_t, pa_time_event_cb_t, POINTER_T(None)] +# pa_context_rttime_restart = _libraries['libpulse.so'] .pa_context_rttime_restart +# pa_context_rttime_restart.restype = None +# pa_context_rttime_restart.argtypes = [POINTER_T(struct_pa_context), POINTER_T(struct_pa_time_event), pa_usec_t] +class struct_pa_sample_spec(ctypes.Structure): + pass + +# pa_context_get_tile_size = _libraries['libpulse.so'] .pa_context_get_tile_size +# pa_context_get_tile_size.restype = size_t +# pa_context_get_tile_size.argtypes = [POINTER_T(struct_pa_context), POINTER_T(struct_pa_sample_spec)] +# pa_context_load_cookie_from_file = _libraries['libpulse.so'] .pa_context_load_cookie_from_file +# pa_context_load_cookie_from_file.restype = ctypes.c_int32 +# pa_context_load_cookie_from_file.argtypes = [POINTER_T(struct_pa_context), ctypes.c_char_p] +# struct_pa_spawn_api._pack_ = True # source:False +# struct_pa_spawn_api._fields_ = [ +# ('prefork', POINTER_T(ctypes.CFUNCTYPE(None))), +# ('postfork', POINTER_T(ctypes.CFUNCTYPE(None))), +# ('atfork', POINTER_T(ctypes.CFUNCTYPE(None))), +# ] +# + +# values for enumeration 'pa_io_event_flags' +pa_io_event_flags__enumvalues = { + 0: 'PA_IO_EVENT_NULL', + 1: 'PA_IO_EVENT_INPUT', + 2: 'PA_IO_EVENT_OUTPUT', + 4: 'PA_IO_EVENT_HANGUP', + 8: 'PA_IO_EVENT_ERROR', +} +PA_IO_EVENT_NULL = 0 +PA_IO_EVENT_INPUT = 1 +PA_IO_EVENT_OUTPUT = 2 +PA_IO_EVENT_HANGUP = 4 +PA_IO_EVENT_ERROR = 8 +pa_io_event_flags = ctypes.c_int # enum +class struct_pa_io_event(ctypes.Structure): + pass + +class struct_pa_defer_event(ctypes.Structure): + pass + +struct_pa_mainloop_api._pack_ = True # source:False +struct_pa_mainloop_api._fields_ = [ + ('userdata', POINTER_T(None)), + ('io_new', POINTER_T(ctypes.CFUNCTYPE(POINTER_T(struct_pa_io_event), POINTER_T(struct_pa_mainloop_api), ctypes.c_int32, pa_io_event_flags, POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_io_event), ctypes.c_int32, pa_io_event_flags, POINTER_T(None))), POINTER_T(None)))), + ('io_enable', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_io_event), pa_io_event_flags))), + ('io_free', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_io_event)))), + ('io_set_destroy', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_io_event), POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_io_event), POINTER_T(None)))))), + ('time_new', POINTER_T(ctypes.CFUNCTYPE(POINTER_T(struct_pa_time_event), POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_timeval), POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_time_event), POINTER_T(struct_timeval), POINTER_T(None))), POINTER_T(None)))), + ('time_restart', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_time_event), POINTER_T(struct_timeval)))), + ('time_free', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_time_event)))), + ('time_set_destroy', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_time_event), POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_time_event), POINTER_T(None)))))), + ('defer_new', POINTER_T(ctypes.CFUNCTYPE(POINTER_T(struct_pa_defer_event), POINTER_T(struct_pa_mainloop_api), POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_defer_event), POINTER_T(None))), POINTER_T(None)))), + ('defer_enable', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_defer_event), ctypes.c_int32))), + ('defer_free', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_defer_event)))), + ('defer_set_destroy', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_defer_event), POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), POINTER_T(struct_pa_defer_event), POINTER_T(None)))))), + ('quit', POINTER_T(ctypes.CFUNCTYPE(None, POINTER_T(struct_pa_mainloop_api), ctypes.c_int32))), +] + +class struct_pollfd(ctypes.Structure): + pass + +class struct_pa_mainloop(ctypes.Structure): + pass + +pa_mainloop = struct_pa_mainloop +pa_mainloop_new = _libraries['libpulse.so'] .pa_mainloop_new +pa_mainloop_new.restype = POINTER_T(struct_pa_mainloop) +pa_mainloop_new.argtypes = [] +pa_mainloop_free = _libraries['libpulse.so'] .pa_mainloop_free +pa_mainloop_free.restype = None +pa_mainloop_free.argtypes = [POINTER_T(struct_pa_mainloop)] + +# pa_mainloop_prepare = _libraries['libpulse.so'] .pa_mainloop_prepare +# pa_mainloop_prepare.restype = ctypes.c_int32 +# pa_mainloop_prepare.argtypes = [POINTER_T(struct_pa_mainloop), ctypes.c_int32] +# pa_mainloop_poll = _libraries['libpulse.so'] .pa_mainloop_poll +# pa_mainloop_poll.restype = ctypes.c_int32 +# pa_mainloop_poll.argtypes = [POINTER_T(struct_pa_mainloop)] +# pa_mainloop_dispatch = _libraries['libpulse.so'] .pa_mainloop_dispatch +# pa_mainloop_dispatch.restype = ctypes.c_int32 +# pa_mainloop_dispatch.argtypes = [POINTER_T(struct_pa_mainloop)] +# pa_mainloop_get_retval = _libraries['libpulse.so'] .pa_mainloop_get_retval +# pa_mainloop_get_retval.restype = ctypes.c_int32 +# pa_mainloop_get_retval.argtypes = [POINTER_T(struct_pa_mainloop)] + +pa_mainloop_iterate = _libraries['libpulse.so'] .pa_mainloop_iterate +pa_mainloop_iterate.restype = ctypes.c_int32 +pa_mainloop_iterate.argtypes = [POINTER_T(struct_pa_mainloop), ctypes.c_int32, POINTER_T(ctypes.c_int32)] + +# pa_mainloop_run = _libraries['libpulse.so'] .pa_mainloop_run +# pa_mainloop_run.restype = ctypes.c_int32 +# pa_mainloop_run.argtypes = [POINTER_T(struct_pa_mainloop), POINTER_T(ctypes.c_int32)] +pa_mainloop_get_api = _libraries['libpulse.so'] .pa_mainloop_get_api +pa_mainloop_get_api.restype = POINTER_T(struct_pa_mainloop_api) +pa_mainloop_get_api.argtypes = [POINTER_T(struct_pa_mainloop)] +# pa_mainloop_quit = _libraries['libpulse.so'] .pa_mainloop_quit +# pa_mainloop_quit.restype = None +# pa_mainloop_quit.argtypes = [POINTER_T(struct_pa_mainloop), ctypes.c_int32] +# pa_mainloop_wakeup = _libraries['libpulse.so'] .pa_mainloop_wakeup +# pa_mainloop_wakeup.restype = None +# pa_mainloop_wakeup.argtypes = [POINTER_T(struct_pa_mainloop)] +# pa_poll_func = POINTER_T(ctypes.CFUNCTYPE(ctypes.c_int32, POINTER_T(struct_pollfd), ctypes.c_uint64, ctypes.c_int32, POINTER_T(None))) +# pa_mainloop_set_poll_func = _libraries['libpulse.so'] .pa_mainloop_set_poll_func +# pa_mainloop_set_poll_func.restype = None +# pa_mainloop_set_poll_func.argtypes = [POINTER_T(struct_pa_mainloop), pa_poll_func, POINTER_T(None)] + +pa_operation_unref = _libraries['libpulse.so'] .pa_operation_unref +pa_operation_unref.restype = None +pa_operation_unref.argtypes = [POINTER_T(struct_pa_operation)] + +# values for enumeration 'pa_sample_format' +# pa_sample_format__enumvalues = { +# 0: 'PA_SAMPLE_U8', +# 1: 'PA_SAMPLE_ALAW', +# 2: 'PA_SAMPLE_ULAW', +# 3: 'PA_SAMPLE_S16LE', +# 4: 'PA_SAMPLE_S16BE', +# 5: 'PA_SAMPLE_FLOAT32LE', +# 6: 'PA_SAMPLE_FLOAT32BE', +# 7: 'PA_SAMPLE_S32LE', +# 8: 'PA_SAMPLE_S32BE', +# 9: 'PA_SAMPLE_S24LE', +# 10: 'PA_SAMPLE_S24BE', +# 11: 'PA_SAMPLE_S24_32LE', +# 12: 'PA_SAMPLE_S24_32BE', +# 13: 'PA_SAMPLE_MAX', +# -1: 'PA_SAMPLE_INVALID', +# } +# PA_SAMPLE_U8 = 0 +# PA_SAMPLE_ALAW = 1 +# PA_SAMPLE_ULAW = 2 +# PA_SAMPLE_S16LE = 3 +# PA_SAMPLE_S16BE = 4 +# PA_SAMPLE_FLOAT32LE = 5 +# PA_SAMPLE_FLOAT32BE = 6 +# PA_SAMPLE_S32LE = 7 +# PA_SAMPLE_S32BE = 8 +# PA_SAMPLE_S24LE = 9 +# PA_SAMPLE_S24BE = 10 +# PA_SAMPLE_S24_32LE = 11 +# PA_SAMPLE_S24_32BE = 12 +# PA_SAMPLE_MAX = 13 +# PA_SAMPLE_INVALID = -1 +# pa_sample_format = ctypes.c_int # enum +# struct_pa_sample_spec._pack_ = True # source:False +# struct_pa_sample_spec._fields_ = [ +# ('format', pa_sample_format), +# ('rate', ctypes.c_uint32), +# ('channels', ctypes.c_ubyte), +# ('PADDING_0', ctypes.c_ubyte * 3), +# ] +# +# struct_timeval._pack_ = True # source:False +# struct_timeval._fields_ = [ +# ('tv_sec', ctypes.c_int64), +# ('tv_usec', ctypes.c_int64), +# ] + +pa_proplist_to_string = _libraries['libpulse.so'].pa_proplist_to_string +pa_proplist_to_string.restype = POINTER_T(ctypes.c_char) +pa_proplist_to_string.argtypes = [POINTER_T(struct_pa_proplist)] + +pa_proplist_gets = _libraries['libpulse.so'].pa_proplist_gets +pa_proplist_gets.restype = POINTER_T(ctypes.c_char) +pa_proplist_gets.argtypes = [POINTER_T(struct_pa_proplist), POINTER_T(ctypes.c_char)] +PA_DIRECTION_OUTPUT = 0x0001 +PA_DIRECTION_INPUT = 0x0002 + + +__all__ = \ + ['PA_CONTEXT_AUTHORIZING', 'PA_CONTEXT_CONNECTING', + 'PA_CONTEXT_FAILED', 'PA_CONTEXT_NOAUTOSPAWN', + 'PA_CONTEXT_NOFAIL', 'PA_CONTEXT_NOFLAGS', 'PA_CONTEXT_READY', + 'PA_CONTEXT_SETTING_NAME', 'PA_CONTEXT_TERMINATED', + 'PA_CONTEXT_UNCONNECTED', 'PA_IO_EVENT_ERROR', + 'PA_IO_EVENT_HANGUP', 'PA_IO_EVENT_INPUT', 'PA_IO_EVENT_NULL', + 'PA_IO_EVENT_OUTPUT', 'PA_SAMPLE_ALAW', 'PA_SAMPLE_FLOAT32BE', + 'PA_SAMPLE_FLOAT32LE', 'PA_SAMPLE_INVALID', 'PA_SAMPLE_MAX', + 'PA_SAMPLE_S16BE', 'PA_SAMPLE_S16LE', 'PA_SAMPLE_S24BE', + 'PA_SAMPLE_S24LE', 'PA_SAMPLE_S24_32BE', 'PA_SAMPLE_S24_32LE', + 'PA_SAMPLE_S32BE', 'PA_SAMPLE_S32LE', 'PA_SAMPLE_U8', + 'PA_SAMPLE_ULAW', 'PA_UPDATE_MERGE', 'PA_UPDATE_REPLACE', + 'PA_UPDATE_SET', 'pa_context', 'pa_context_connect', + 'pa_context_disconnect', 'pa_context_drain', 'pa_context_errno', + 'pa_context_event_cb_t', 'pa_context_exit_daemon', + 'pa_context_flags', 'pa_context_flags_t', + 'pa_context_flags_t__enumvalues', 'pa_context_get_index', + 'pa_context_get_protocol_version', 'pa_context_get_server', + 'pa_context_get_server_protocol_version', 'pa_context_get_state', + 'pa_context_get_tile_size', 'pa_context_is_local', + 'pa_context_is_pending', 'pa_context_load_cookie_from_file', + 'pa_context_new', 'pa_context_new_with_proplist', + 'pa_context_notify_cb_t', 'pa_context_proplist_remove', + 'pa_context_proplist_update', 'pa_context_ref', + 'pa_context_rttime_new', 'pa_context_rttime_restart', + 'pa_context_set_default_sink', 'pa_context_set_default_source', + 'pa_context_set_event_callback', 'pa_context_set_name', + 'pa_context_set_state_callback', 'pa_context_state', + 'pa_context_state_t', 'pa_context_state_t__enumvalues', + 'pa_context_success_cb_t', 'pa_context_unref', + 'pa_io_event_flags', 'pa_mainloop', 'pa_mainloop_dispatch', + 'pa_mainloop_free', 'pa_mainloop_get_api', + 'pa_mainloop_get_retval', 'pa_mainloop_iterate', + 'pa_mainloop_new', 'pa_mainloop_poll', 'pa_mainloop_prepare', + 'pa_mainloop_quit', 'pa_mainloop_run', + 'pa_mainloop_set_poll_func', 'pa_mainloop_wakeup', 'pa_poll_func', + 'pa_sample_format', 'pa_time_event_cb_t', 'pa_update_mode', + 'pa_update_mode_t', 'pa_update_mode_t__enumvalues', 'pa_usec_t', + 'size_t', 'struct_pa_context', 'struct_pa_defer_event', + 'struct_pa_io_event', 'struct_pa_mainloop', + 'struct_pa_mainloop_api', 'struct_pa_operation', + 'struct_pa_proplist', 'struct_pa_sample_spec', + 'struct_pa_spawn_api', 'struct_pa_time_event', 'struct_pollfd', + 'struct_timeval', 'uint32_t','pa_proplist_to_string','pa_proplist_gets','PA_DIRECTION_OUTPUT', 'PA_DIRECTION_INPUT'] diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/pa_helper.py b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/pa_helper.py new file mode 100644 index 0000000..6ec79a0 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/extensions/sound-output-device-chooser@kgshank.net/utils/pa_helper.py @@ -0,0 +1,141 @@ +#!/usr/bin/python +############################################################################### + # 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 . + # + # Original Author: Gopi Sankar Karmegam + ############################################################################## + +import libpulse_introspect as pa +import sys +from ctypes import c_int,byref, c_char_p, cast +import time +from json import dumps + +class PAHelper(): + + _error = { + 'success': False, + 'error': None, + } + _card_op_done = None + _pa_state = pa.PA_CONTEXT_UNCONNECTED + + + def __init__(self): + self._ports = [] + self._cards = {} + self.mainloop = pa.pa_mainloop_new() + self._context = pa.pa_context_new( pa.pa_mainloop_get_api(self.mainloop), b'PAHelper') + self._pa_context_notify_cb_t = pa.pa_context_notify_cb_t(self.pa_context_notify_cb_t) + pa.pa_context_set_state_callback(self._context, self._pa_context_notify_cb_t , None) + pa.pa_context_connect(self._context, None, 0, None) + self._opn_completed = False + + def print_card_info(self, index = None): + operation = None + retVal = c_int() + counter = 0 + + while counter < 10000 and self._opn_completed == False: + counter += 1 + if self._pa_state == pa.PA_CONTEXT_READY and operation == None: + self._pa_card_info_cb_t = pa.pa_card_info_cb_t(self.pa_card_info_cb) +# operation = pa.pa_context_get_card_info_by_index(self._context, +# index, self._pa_card_info_cb_t , None) + operation = pa.pa_context_get_card_info_list(self._context, + self._pa_card_info_cb_t , None) + + pa.pa_mainloop_iterate(self.mainloop, 0, byref(retVal)) + print(dumps({'cards': self._cards, 'ports':self._ports}, indent = 5)) + + try: + if operation: + pa.pa_operation_unref(operation) + + pa.pa_context_disconnect(self._context) + pa.pa_context_unref(self._context) + pa.pa_mainloop_free(self.mainloop) + except: + pass + + def pa_card_info_cb(self, context, card_info, eol, whatever): + + if not card_info or not card_info[0]: + return + + card = card_info[0] + #print (card.index) + card_obj = {} + card_obj['index'] = str(card.index) + self._cards[card.index] = card_obj + card_obj['profiles'] = [] + + card_name = cast(pa.pa_proplist_gets(card.proplist,c_char_p(b'alsa.card_name')),c_char_p) + card_obj['alsa_name'] = card_name.value.decode('utf8') if card_name else '' + description = cast(pa.pa_proplist_gets(card.proplist,c_char_p(b'device.description')),c_char_p) + card_obj['card_description'] = description.value.decode('utf8') if description else '' + + card_obj['name'] = card.name.decode('utf8') if card.name else '' + for k in range(0, card.n_profiles): + if(card.profiles2[k]): + profile = card.profiles2[k].contents + pobj = {} + pobj['name'] = profile.name.decode('utf8') if profile.name else '' + pobj['human_name'] = profile.description.decode('utf8') if profile.description else '' + pobj['available'] = profile.available + card_obj['profiles'].append(pobj) + + card_obj['ports'] = [] + for i in range(0, card.n_ports): + port = card.ports[i].contents +# print ("Port name "+ str(port.name)) + obj = {} + obj['name'] = port.name.decode('utf8') if port.name else '' + obj['human_name'] = port.description.decode('utf8') if port.description else '' + obj['direction'] = 'Output' if (port.direction & pa.PA_DIRECTION_OUTPUT) else 'Input' + obj['available'] = port.available + obj['n_profiles'] = port.n_profiles + obj['profiles'] = [] + obj['card_name'] = card_obj['name'] + obj['card_description'] = card_obj['card_description'] + for j in range(0, port.n_profiles): + if(port.profiles2[j]): + profile = port.profiles2[j].contents +# pobj = {} +# pobj['name'] = profile.name.decode('utf8') if profile.name else '' +# pobj['human_name'] = profile.description.decode('utf8') if profile.description else '' +# pobj['available'] = profile.available +# obj['profiles'].append(pobj) + if profile.name: + obj['profiles'].append(profile.name.decode('utf8')) + + self._ports.append(obj) + card_obj['ports'].append(obj) + + + + self._opn_completed = True + + + def pa_context_notify_cb_t(self, context, userdata): + try: + self._pa_state = pa.pa_context_get_state(context) + + except Exception: + self._pa_state = pa.PA_CONTEXT_FAILED + + +PAHelper().print_card_info() + + diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/gnome b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/gnome new file mode 100644 index 0000000..76933ca --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/gnome @@ -0,0 +1,156 @@ +# Calculate format=dconf dconf=/org/gnome + +[desktop/app-folders] +folder-children=['Utilities', 'YaST', 'Sound & Video', 'Graphics', 'Internet', 'Office', 'System Tools', 'Accessories', 'Settings'] + +[desktop/app-folders/folders/Accessories] +apps=['org.gnome.Extensions.desktop', 'org.gnome.Weather.desktop'] +categories=['Utility'] +name='Utility.directory' +translate=true + +[desktop/app-folders/folders/Graphics] +apps=['zzz-gimp.desktop', 'org.fontforge.FontForge.desktop', 'shotwell.desktop'] +categories=['Graphics'] +name='Graphics.directory' +translate=true + +[desktop/app-folders/folders/Internet] +apps=['org.gnome.Epiphany.desktop', 'org.gajim.Gajim.desktop', 'transmission-gtk.desktop', 'org.remmina.Remmina.desktop', 'spicy-spice-gtk.desktop'] +categories=['Network'] +name='Network.directory' +translate=true + +[desktop/app-folders/folders/Office] +apps=['FBReader.desktop', 'libreoffice-base.desktop', 'libreoffice-calc.desktop', 'libreoffice-draw.desktop', 'libreoffice-impress.desktop', 'libreoffice-math.desktop', 'libreoffice-writer.desktop', 'org.gnome.Contacts.desktop', 'gucharmap.desktop'] +categories=['Office'] +name='Office.directory' +translate=true + +[desktop/app-folders/folders/Settings] +apps=['Gentoo-system-config-printer.desktop', 'org.gnome.Settings.desktop', 'cl-console-gui.desktop', 'nm-connection-editor.desktop'] +categories=['Settings'] +name='SystemSettings.directory' +translate=true + +[desktop/app-folders/folders/Sound & Video] +apps=['brasero.desktop', 'org.gnome.Cheese.desktop', 'org.gnome.SoundJuicer.desktop'] +categories=['AudioVideo'] +name='AudioVideo.directory' +translate=true + +[desktop/app-folders/folders/System Tools] +apps=['gparted.desktop', 'cpu-x-root.desktop', 'cpu-x.desktop', 'virt-manager.desktop', 'ca.desrt.dconf-editor.desktop'] +categories=['System'] +name='System-Tools.directory' +translate=true + +[desktop/app-folders/folders/Utilities] +apps=['gnome-abrt.desktop', 'gnome-system-log.desktop', 'nm-connection-editor.desktop', 'org.gnome.baobab.desktop', 'org.gnome.Connections.desktop', 'org.gnome.DejaDup.desktop', 'org.gnome.Dictionary.desktop', 'org.gnome.DiskUtility.desktop', 'org.gnome.eog.desktop', 'org.gnome.Evince.desktop', 'org.gnome.FileRoller.desktop', 'org.gnome.fonts.desktop', 'org.gnome.seahorse.Application.desktop', 'org.gnome.tweaks.desktop', 'org.gnome.Usage.desktop', 'vinagre.desktop', 'gnome-system-monitor.desktop', 'simple-scan.desktop'] +categories=['X-GNOME-Utilities'] +name='X-GNOME-Utilities.directory' +translate=true + +[desktop/app-folders/folders/YaST] +categories=['X-SuSE-YaST'] +name='suse-yast.directory' +translate=true + +[desktop/background] +color-shading-type='solid' +picture-options='zoom' +picture-uri='file:///usr/share/backgrounds/calculate/Calculate%20Linux%2011%20Blue.jpg' +picture-uri-dark='file:///usr/share/backgrounds/calculate/Calculate%20Linux%2011%20Brown.jpg' +primary-color='#000000' +secondary-color='#000000' + +[desktop/input-sources] +sources=[('xkb', 'us'), ('xkb', 'ru')] +xkb-options=['grp:alt_shift_toggle'] + +[desktop/interface] +color-scheme='prefer-dark' +cursor-theme='Adwaita' +enable-animations=true +font-antialiasing='grayscale' +font-hinting='slight' +gtk-theme='Adwaita-dark' +icon-theme='Adwaita' + +[desktop/privacy] +disable-microphone=false + +[desktop/screensaver] +color-shading-type='solid' +picture-options='zoom' +picture-uri='file:///usr/share/backgrounds/calculate/Calculate%20Linux%2015.jpg' +primary-color='#000000' +secondary-color='#000000' + +[desktop/session] +idle-delay=uint32 900 + +[desktop/wm/preferences] +button-layout='appmenu:minimize,maximize,close' + +[gedit/preferences/editor] +scheme='oblivion' +wrap-last-split-mode='word' + +[shell] +app-picker-layout=[{'Sound & Video': <{'position': <0>}>, 'Graphics': <{'position': <1>}>, 'Internet': <{'position': <2>}>, 'Office': <{'position': <3>}>, 'System Tools': <{'position': <4>}>, 'Accessories': <{'position': <5>}>, 'Utilities': <{'position': <6>}>, 'Settings': <{'position': <7>}>}] +disable-user-extensions=false +enabled-extensions=['user-theme@gnome-shell-extensions.gcampax.github.com', 'appindicatorsupport@rgcjonas.gmail.com', 'tweaks-system-menu@extensions.gnome-shell.fifi.org', 'applications-overview-tooltip@RaphaelRochet', 'ControlBlurEffectOnLockScreen@pratap.fastmail.fm', 'dash-to-dock@micxgx.gmail.com', 'MaximizeToEmptyWorkspace-extension@kaisersite.de', 'no-overview@fthx', 'ding@rastersoft.com', 'RemoveAppMenu@Dragon8oy.com', 'blur-my-shell@aunetx'] +favorite-apps=['firefox.desktop', 'org.gnome.Evolution.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Polari.desktop', 'libreoffice-startcenter.desktop', 'org.gnome.Calculator.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Music.desktop', 'org.gnome.Totem.desktop', 'org.gnome.gedit.desktop', 'org.gnome.Terminal.desktop', 'org.gnome.Nautilus.desktop', 'cl-console-gui-update.desktop'] + +[shell/extensions/blur-my-shell/applications] +blur=false + +[shell/extensions/blur-my-shell/dash-to-dock] +blur=false + +[shell/extensions/blur-my-shell/overview] +blur=true +brightness=0.80000000000000004 +customize=true +style-components=1 + +[shell/extensions/blur-my-shell/panel] +blur=true +brightness=0.68000000000000005 +customize=true +override-background-dynamically=true +static-blur=true +style-panel=0 +unblur-dynamically=true +unblur-in-overview=false + +[shell/extensions/dash-to-dock] +apply-custom-theme=false +background-opacity=0.80000000000000004 +custom-background-color=false +custom-theme-shrink=true +dash-max-icon-size=42 +dock-position='BOTTOM' +height-fraction=0.90000000000000002 +preferred-monitor=-2 +show-apps-at-top=false +transparency-mode='DYNAMIC' + +[shell/extensions/dash-to-panel] +available-monitors=[0] + +[shell/extensions/ding] +show-home=false +show-trash=false +show-volumes=false + +[shell/extensions/shutdowntimer-deminder] +preferences-selected-page-value=4 +shutdown-timestamp-value=-1 + +[terminal/legacy] +theme-variant='dark' + +[tweaks] +show-extensions-notice=false diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/ini.env b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/ini.env new file mode 100644 index 0000000..18695b7 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/ini.env @@ -0,0 +1,11 @@ +# Calculate format=samba path=~/.calculate + +[ver] +#?pkg(gnome-base/gnome-shell)>=40# +gnome = 40.0 +#!pkg# +gnome = 3.0 +#pkg# + +[update] +gnome = on diff --git a/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/user-folders.lst b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/user-folders.lst new file mode 100644 index 0000000..ad40ec2 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/2-user/gnome-base/Gnome-40.0/user-folders.lst @@ -0,0 +1 @@ +# Calculate path=~/.local/share/backgrounds diff --git a/profiles/templates/6_ac_desktop_profile/README-eng.txt b/profiles/templates/6_ac_desktop_profile/README-eng.txt new file mode 100644 index 0000000..228e706 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/README-eng.txt @@ -0,0 +1,8 @@ +# Calculate append=skip + +The ac_desktop_profile event: +- package installation +- user profile configuration + +Action: package configuration within a user profile +env: desktop diff --git a/profiles/templates/6_ac_desktop_profile/README-rus.txt b/profiles/templates/6_ac_desktop_profile/README-rus.txt new file mode 100644 index 0000000..5df4536 --- /dev/null +++ b/profiles/templates/6_ac_desktop_profile/README-rus.txt @@ -0,0 +1,8 @@ +# Calculate append=skip + +Событие ac_desktop_profile: +- установка пакета +- настройка профиля пользователя + +Действие: настройка пакета в профиле пользователя +env: desktop \ No newline at end of file diff --git a/profiles/templates/6_ac_install_configure/.calculate_directory b/profiles/templates/6_ac_install_configure/.calculate_directory new file mode 100644 index 0000000..986581c --- /dev/null +++ b/profiles/templates/6_ac_install_configure/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip env=install ac_install_configure==on diff --git a/profiles/templates/6_ac_install_configure/README-eng.txt b/profiles/templates/6_ac_install_configure/README-eng.txt new file mode 100644 index 0000000..e9f97db --- /dev/null +++ b/profiles/templates/6_ac_install_configure/README-eng.txt @@ -0,0 +1,7 @@ +# Calculate append=skip + +ac_install_configure event: +- System setup with 'cl-setup-*' + +Action: calling templates for system configuration +env: install diff --git a/profiles/templates/6_ac_install_configure/README-rus.txt b/profiles/templates/6_ac_install_configure/README-rus.txt new file mode 100644 index 0000000..82e15c4 --- /dev/null +++ b/profiles/templates/6_ac_install_configure/README-rus.txt @@ -0,0 +1,8 @@ +# Calculate append=skip + +Событие ac_install_configure: +- настройка системы при помощи утилит 'cl-setup-*' + +Действие: Вызовы шаблонов настройки компонентов системы +env: install + diff --git a/profiles/templates/6_ac_install_configure/session b/profiles/templates/6_ac_install_configure/session new file mode 100644 index 0000000..4376773 --- /dev/null +++ b/profiles/templates/6_ac_install_configure/session @@ -0,0 +1,7 @@ +# Calculate format=samba merge=x11-misc/sddm,x11-base/xorg-server,x11-misc/lightdm,gnome-base/gdm cl_setup==session||cl_setup== path=/var/lib/calculate name=calculate.env + +[main] +cl_home_crypt_set = #-cl_install_home_crypt_set-# + +[install] +cl_autologin = #-cl_autologin-# diff --git a/profiles/templates/6_ac_update_sync/.calculate_directory b/profiles/templates/6_ac_update_sync/.calculate_directory new file mode 100644 index 0000000..6cc8a04 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip env=update ac_update_sync==on diff --git a/profiles/templates/6_ac_update_sync/README-eng.txt b/profiles/templates/6_ac_update_sync/README-eng.txt new file mode 100644 index 0000000..2996b91 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/README-eng.txt @@ -0,0 +1,7 @@ +# Calculate append=skip + +The ac_update_sync event: +- Portage syncing + +Action: world update, fix system +env: install diff --git a/profiles/templates/6_ac_update_sync/README-rus.txt b/profiles/templates/6_ac_update_sync/README-rus.txt new file mode 100644 index 0000000..fe3ae65 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/README-rus.txt @@ -0,0 +1,7 @@ +# Calculate append=skip + +Событие ac_update_sync: +- обновление портежей + +Действие: обновление world файла, исправление системы +env: install diff --git a/profiles/templates/6_ac_update_sync/world/.calculate_directory b/profiles/templates/6_ac_update_sync/world/.calculate_directory new file mode 100644 index 0000000..28b07ff --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/.calculate_directory @@ -0,0 +1 @@ +# Calculate path=/var/lib name=portage \ No newline at end of file diff --git a/profiles/templates/6_ac_update_sync/world/0-ini b/profiles/templates/6_ac_update_sync/world/0-ini new file mode 100644 index 0000000..8bf0886 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/0-ini @@ -0,0 +1,4 @@ +# Calculate path=/var/lib/calculate name=ini.env format=samba cl_update_world==rebuild||cl_update_world==merge||ini(gnome-profile.world)== + +[gnome-profile] +world = 20220905 diff --git a/profiles/templates/6_ac_update_sync/world/create/.calculate_directory b/profiles/templates/6_ac_update_sync/world/create/.calculate_directory new file mode 100644 index 0000000..efc7485 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip cl_update_world==merge||cl_update_world==rebuild diff --git a/profiles/templates/6_ac_update_sync/world/create/applications b/profiles/templates/6_ac_update_sync/world/create/applications new file mode 100644 index 0000000..765466c --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/applications @@ -0,0 +1,13 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +app-office/libreoffice +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-text/fbreader +#in# + +#?in(os_linux_pkglist, CLDG)!=# +sys-apps/flatpak +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/base b/profiles/templates/6_ac_update_sync/world/create/base new file mode 100644 index 0000000..ccad521 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/base @@ -0,0 +1,11 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, calculate)!=# +app-editors/nano +media-fonts/terminus-font +sys-apps/busybox +sys-apps/calculate-toolkit +sys-apps/ifplugd +sys-apps/less +sys-kernel/dracut +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/decoration b/profiles/templates/6_ac_update_sync/world/create/decoration new file mode 100644 index 0000000..df02c19 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/decoration @@ -0,0 +1,23 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/grub-splashes-calculate +#in# + +#?in(os_linux_pkglist, CLDG)!=# +media-fonts/noto-emoji +media-gfx/calculate-wallpapers +media-gfx/dm-themes-calculate +media-gfx/splash-themes-calculate +x11-themes/calculate-icon-theme +#in# + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/lightdm-themes-calculate +x11-themes/adwaita-qt +#in# + +#?in(os_linux_pkglist, CLDG)!=# +x11-misc/qt5ct +#in# + diff --git a/profiles/templates/6_ac_update_sync/world/create/gnome b/profiles/templates/6_ac_update_sync/world/create/gnome new file mode 100644 index 0000000..1dc9bff --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/gnome @@ -0,0 +1,18 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +gnome-base/gnome +gnome-extra/gnome-shell-extension-appindicator +gnome-extra/gnome-shell-extension-applications-overview-tooltip +gnome-extra/gnome-shell-extension-control-blur-effect-on-lock-screen +gnome-extra/gnome-shell-extension-dash-to-dock +gnome-extra/gnome-shell-extension-dash-to-panel +gnome-extra/gnome-shell-extension-desktop-icons-ng +gnome-extra/gnome-shell-extension-maximize-to-empty-workspace +gnome-extra/gnome-shell-extension-no-overview +gnome-extra/gnome-shell-extension-remove-app-menu +gnome-extra/gnome-shell-extension-tweaks-system-menu +gnome-extra/gnome-power-manager +sys-power/power-profiles-daemon +net-irc/polari +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/graphics b/profiles/templates/6_ac_update_sync/world/create/graphics new file mode 100644 index 0000000..91a9dd0 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/graphics @@ -0,0 +1,10 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +sys-firmware/nvidia-firmware +#in# + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/imagemagick +#in# + diff --git a/profiles/templates/6_ac_update_sync/world/create/multimedia b/profiles/templates/6_ac_update_sync/world/create/multimedia new file mode 100644 index 0000000..77aa662 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/multimedia @@ -0,0 +1,8 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +media-plugins/alsa-plugins +media-sound/alsa-utils +media-sound/bluez-alsa +sys-firmware/sof-firmware +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/netapps b/profiles/templates/6_ac_update_sync/world/create/netapps new file mode 100644 index 0000000..dad7c0e --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/netapps @@ -0,0 +1,22 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +app-text/wgetpaste +net-analyzer/nmap +net-analyzer/traceroute +net-dns/bind-tools +net-misc/ntp +net-misc/whois +#in# + +#?in(os_linux_pkglist, CLDG)!=# +www-client/firefox +#in# + +#?in(os_linux_pkglist, CLDG)!=# +net-im/gajim +net-misc/remmina +net-p2p/transmission +x11-misc/x11vnc +#in# + diff --git a/profiles/templates/6_ac_update_sync/world/create/network b/profiles/templates/6_ac_update_sync/world/create/network new file mode 100644 index 0000000..b2ad828 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/network @@ -0,0 +1,17 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +net-dialup/pptpclient +net-dialup/rp-pppoe +net-dialup/xl2tpd +net-firewall/shorewall +#in# + +#?in(os_linux_pkglist, CLDG)!=# +net-vpn/networkmanager-l2tp +net-vpn/networkmanager-openvpn +net-vpn/networkmanager-pptp +net-vpn/networkmanager-vpnc +net-vpn/networkmanager-wireguard +#in# + diff --git a/profiles/templates/6_ac_update_sync/world/create/printer b/profiles/templates/6_ac_update_sync/world/create/printer new file mode 100644 index 0000000..9fde16e --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/printer @@ -0,0 +1,22 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/epsonscan2 +net-print/cndrvcups-common-lb +net-print/cnijfilter2 +net-print/cups +net-print/epson-inkjet-printer-escpr +net-print/foomatic-db-engine +net-print/gutenprint +net-print/hplip +net-print/hplip-plugin +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-admin/system-config-printer +#in# + + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/simple-scan +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/tools b/profiles/templates/6_ac_update_sync/world/create/tools new file mode 100644 index 0000000..63593ef --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/tools @@ -0,0 +1,87 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +app-arch/lbzip2 +app-arch/pigz +app-misc/tmux +app-text/tree +net-misc/dhcp +sys-auth/pam_update +sys-fs/btrfs-progs +sys-fs/cryptsetup +sys-fs/f2fs-tools +sys-fs/reiserfsprogs +sys-fs/xfsprogs +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-admin/logrotate +app-admin/syslog-ng +sys-apps/ethtool +sys-apps/usbutils +sys-process/cronie +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-editors/vim +app-vim/colorschemes +sys-apps/inxi +sys-fs/mdadm +sys-process/htop +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-admin/hddtemp +app-admin/sudo +app-admin/testdisk +app-cdr/cdrtools +app-cdr/dvd+rw-tools +app-misc/mc +app-portage/portage-utils +sys-apps/acl +sys-apps/dmidecode +sys-apps/lm-sensors +sys-apps/memtest86+ +sys-apps/pciutils +sys-apps/pv +sys-apps/smartmontools +sys-fs/dmraid +sys-fs/dosfstools +sys-fs/mtools +sys-fs/ncdu +sys-process/lsof +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-arch/p7zip +app-arch/rar +app-arch/unzip +sys-apps/hdparm +sys-apps/keyexec +sys-apps/pcmciautils +sys-apps/usb_modeswitch +sys-fs/exfatprogs +sys-fs/ntfs3g +sys-power/acpi +sys-power/acpid +sys-power/cpupower +sys-power/powernowd +sys-power/powertop +#in# + +#?in(os_linux_pkglist, CLDG)!=# +sys-power/upower +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-pda/usbmuxd +dev-python/gst-python +sys-block/gparted +#для корректной поддержки мультимедиа клавиатур +x11-misc/wmctrl +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-portage/cpuid2cpuflags +app-misc/resolve-march-native +#in# diff --git a/profiles/templates/6_ac_update_sync/world/create/wireless b/profiles/templates/6_ac_update_sync/world/create/wireless new file mode 100644 index 0000000..5dc9c58 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/wireless @@ -0,0 +1,15 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +net-wireless/broadcom-sta +net-wireless/rtl8814au +net-wireless/rtl8821ce +net-wireless/rtl8821cu +net-wireless/rtl88x2bu +net-wireless/wireless-tools +net-wireless/wpa_supplicant +sys-firmware/b43-firmware +sys-firmware/ipw2100-firmware +sys-firmware/ipw2200-firmware +#in# + diff --git a/profiles/templates/6_ac_update_sync/world/create/xorg b/profiles/templates/6_ac_update_sync/world/create/xorg new file mode 100644 index 0000000..846df85 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/create/xorg @@ -0,0 +1,13 @@ +# Calculate name=world format=world + +#?in(os_linux_pkglist, CLDG)!=# +app-misc/xorg-meta +#in# + +#?in(os_linux_pkglist, CLDG)!=# +app-i18n/uim +#in# + +#?in(os_linux_pkglist, CLDG)!=# +x11-misc/lightdm +#in# diff --git a/profiles/templates/6_ac_update_sync/world/update/.calculate_directory b/profiles/templates/6_ac_update_sync/world/update/.calculate_directory new file mode 100644 index 0000000..06d9075 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip cl_update_world!=merge&&cl_update_world!=rebuild diff --git a/profiles/templates/6_ac_update_sync/world/update/2022/.calculate_directory b/profiles/templates/6_ac_update_sync/world/update/2022/.calculate_directory new file mode 100644 index 0000000..60d90d1 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/2022/.calculate_directory @@ -0,0 +1 @@ +# Calculate append=skip ini(overlay-distros.world)<20230101 diff --git a/profiles/templates/6_ac_update_sync/world/update/2022/20220204 b/profiles/templates/6_ac_update_sync/world/update/2022/20220204 new file mode 100644 index 0000000..059ba7b --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/2022/20220204 @@ -0,0 +1,5 @@ +# Calculate format=world name=world ini(overlay-distros.world)<#-cut()-# + +#-ini(overlay-distros.world,#-cut()-#)-# + +!media-gfx/utsushi diff --git a/profiles/templates/6_ac_update_sync/world/update/2022/20220420 b/profiles/templates/6_ac_update_sync/world/update/2022/20220420 new file mode 100644 index 0000000..72a1baf --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/2022/20220420 @@ -0,0 +1,5 @@ +# Calculate format=world name=world ini(overlay-distros.world)<#-cut()-# + +#-ini(overlay-distros.world,#-cut()-#)-# + +!net-misc/vinagre diff --git a/profiles/templates/6_ac_update_sync/world/update/2022/20220805 b/profiles/templates/6_ac_update_sync/world/update/2022/20220805 new file mode 100644 index 0000000..3b30621 --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/2022/20220805 @@ -0,0 +1,5 @@ +# Calculate format=world name=world ini(overlay-distros.world)<#-cut()-# + +#-ini(overlay-distros.world,#-cut()-#)-# + +!sys-process/cpu-x diff --git a/profiles/templates/6_ac_update_sync/world/update/2022/20220905 b/profiles/templates/6_ac_update_sync/world/update/2022/20220905 new file mode 100644 index 0000000..a3ae3bd --- /dev/null +++ b/profiles/templates/6_ac_update_sync/world/update/2022/20220905 @@ -0,0 +1,7 @@ +# Calculate format=world name=world ini(overlay-distros.world)<#-cut()-# + +#-ini(overlay-distros.world,#-cut()-#)-# + +#?in(os_linux_pkglist, CLDG)!=# +media-gfx/epsonscan2 +#in# diff --git a/sys-power/power-profiles-daemon/Manifest b/sys-power/power-profiles-daemon/Manifest new file mode 100644 index 0000000..0c8ccb6 --- /dev/null +++ b/sys-power/power-profiles-daemon/Manifest @@ -0,0 +1,7 @@ +AUX power-profiles-daemon.confd 49 BLAKE2B 22d24c4826d99e27dfe3fd7ece09af8e610c09fac6e3cd85bcec976a0cae52eac244383fc9606546e3dd08b0ba0207cccac9e035b25ffcbb46b4c81c5d81ec9f SHA512 6f8fdcc7f7cd3e8d0aea8a61befc168dcf3e5701c9b814de72b47b95f5280e1c2a646b7f45a68895c73a9625a9b5cb379233b1935fd2a6a39427cff2160fe323 +AUX power-profiles-daemon.initd 299 BLAKE2B c5af2c1b1a899d0497a093ecf33c6e9c25c97005f94903720847c2cd65451196446ed3705f15dba2a53e2991c4c2f2944c9ffa1aca9431ab59d7e2308e4ddbeb SHA512 6dea5b8b7b4f28a4379d97983e76bbc89210d8685735d1d3ea5c1a75c2f5f37899ef17fc5d5bedadc859d29a69927faa9b55356af2bdac15c250c57cfefaf4c4 +AUX power-profiles-daemon.tmpfiles 58 BLAKE2B 4448feb0622ee95017b38dd0cc54a012df20132d4e409dc80ddea2137132892c3d596f752829b5644dc5f4aa420a6f0b050824e775881920982b96fdd9783ee5 SHA512 35a32bb666e3bc84c304823775e4671b736fdaf07f74ee0806e6c201edbd9c76121d11e96457eb1a126136c7ba4d2516aa9f691d24813da62c06c7da39519199 +DIST power-profiles-daemon-0.11.1.tar.gz 54336 BLAKE2B 53514a3de851da349b39e0261a1ce4cdd7e3e62ed08d1ed7374518132e1f5ce2230ae869c34c7461bcdaf4eb89b9d78360526ac7e21c525c09de31bd19503ab4 SHA512 0fedb425675b153897b2e257fd71b37bb26f3fde849b5e9f6c972feb54a2d80bf6584322ff0a4edd1f2bab67d62136924491be47ea391ca263f40a92a86ab4e4 +DIST power-profiles-daemon-0.12.tar.gz 55705 BLAKE2B 7e78744186d1175d7dc67e3fe84481f68e14ed409639a44bd834ffae820b0828428271360f4f7faa0e2c2323f2ce4d1061e1b260b74aaf5da5cd35881def4a6f SHA512 d6645432751cbf94166307d2d3f982a598c28c0541bda666bc04c2da68ca7d0a129209312a9e6437fe80b786d7040ea34e5e921bc23f0a8d554f72fac1aada5a +EBUILD power-profiles-daemon-0.11.1.ebuild 1285 BLAKE2B 64459bf89380a5f3ad6f2e9df3970d154ea00022767edbe56ae40711e4d0d50855a0036ebc8cd8fdf3e8bb8e902cfb6d1bb787dc986f9333781428eea3f56b14 SHA512 50b29424434b34fca29a45f01c82ace40036c36a5d3e6d425dc471718d60266fbf913b3f01e06a225545218908c100f8f6451da768b46028d0f10a4ea861d3a8 +EBUILD power-profiles-daemon-0.12.ebuild 1285 BLAKE2B 64459bf89380a5f3ad6f2e9df3970d154ea00022767edbe56ae40711e4d0d50855a0036ebc8cd8fdf3e8bb8e902cfb6d1bb787dc986f9333781428eea3f56b14 SHA512 50b29424434b34fca29a45f01c82ace40036c36a5d3e6d425dc471718d60266fbf913b3f01e06a225545218908c100f8f6451da768b46028d0f10a4ea861d3a8 diff --git a/sys-power/power-profiles-daemon/files/power-profiles-daemon.confd b/sys-power/power-profiles-daemon/files/power-profiles-daemon.confd new file mode 100644 index 0000000..de3fd31 --- /dev/null +++ b/sys-power/power-profiles-daemon/files/power-profiles-daemon.confd @@ -0,0 +1,3 @@ +# /etc/conf.d/power-profiles-daemon + +#PPDARGS="" diff --git a/sys-power/power-profiles-daemon/files/power-profiles-daemon.initd b/sys-power/power-profiles-daemon/files/power-profiles-daemon.initd new file mode 100644 index 0000000..d483e82 --- /dev/null +++ b/sys-power/power-profiles-daemon/files/power-profiles-daemon.initd @@ -0,0 +1,13 @@ +#!/sbin/openrc-run +# Copyright 2022 Calculate Linux by jksf +# Distributed under the terms of the GNU General Public License v2 + +command="/usr/libexec/power-profiles-daemon" +command_args="${PPDARGS}" +supervisor="supervise-daemon" +command_args_foreground="" + +depend() { + use clock logger + need dbus +} diff --git a/sys-power/power-profiles-daemon/files/power-profiles-daemon.tmpfiles b/sys-power/power-profiles-daemon/files/power-profiles-daemon.tmpfiles new file mode 100644 index 0000000..8b8c70d --- /dev/null +++ b/sys-power/power-profiles-daemon/files/power-profiles-daemon.tmpfiles @@ -0,0 +1 @@ +f /var/lib/power-profiles-daemon/state.ini 0644 root root diff --git a/sys-power/power-profiles-daemon/power-profiles-daemon-0.11.1.ebuild b/sys-power/power-profiles-daemon/power-profiles-daemon-0.11.1.ebuild new file mode 100644 index 0000000..9600602 --- /dev/null +++ b/sys-power/power-profiles-daemon/power-profiles-daemon-0.11.1.ebuild @@ -0,0 +1,50 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit meson systemd + +DESCRIPTION="Makes power profiles handling available over D-Bus." +HOMEPAGE="https://gitlab.freedesktop.org/hadess/power-profiles-daemon" +SRC_URI="https://gitlab.freedesktop.org/hadess/${PN}/-/archive/${PV}/${PN}-${PV}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +IUSE="doc" + +KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~riscv ~x86" + +BDEPEND=">=dev-libs/libgudev-234 + >=sys-auth/polkit-0.114 + sys-power/upower + dev-util/umockdev + dev-python/python-dbusmock +" +DEPEND="${BDEPEND}" + +src_configure() { + local emesonargs=( + $(meson_use doc gtk_doc) + -Dsystemdsystemunitdir=$(systemd_get_systemunitdir) + ) + meson_src_configure +} + +src_install() { + meson_src_install + + exeinto /etc/init.d/ + newexe "${FILESDIR}/power-profiles-daemon.initd" power-profiles-daemon + + exeinto /etc/conf.d/ + newexe "${FILESDIR}/power-profiles-daemon.confd" power-profiles-daemon + + exeinto /usr/lib/tmpfiles.d/ + newexe "${FILESDIR}/power-profiles-daemon.tmpfiles" power-profiles-daemon.conf +} + +pkg_postinst() { + ewarn "Don't forget to enable \"${PN}\" service, by runnning:" + ewarn "rc-update add ${PN} default && rc-service ${PN} start" +} diff --git a/sys-power/power-profiles-daemon/power-profiles-daemon-0.12.ebuild b/sys-power/power-profiles-daemon/power-profiles-daemon-0.12.ebuild new file mode 100644 index 0000000..9600602 --- /dev/null +++ b/sys-power/power-profiles-daemon/power-profiles-daemon-0.12.ebuild @@ -0,0 +1,50 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit meson systemd + +DESCRIPTION="Makes power profiles handling available over D-Bus." +HOMEPAGE="https://gitlab.freedesktop.org/hadess/power-profiles-daemon" +SRC_URI="https://gitlab.freedesktop.org/hadess/${PN}/-/archive/${PV}/${PN}-${PV}.tar.gz" + +LICENSE="GPL-3+" +SLOT="0" +IUSE="doc" + +KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~riscv ~x86" + +BDEPEND=">=dev-libs/libgudev-234 + >=sys-auth/polkit-0.114 + sys-power/upower + dev-util/umockdev + dev-python/python-dbusmock +" +DEPEND="${BDEPEND}" + +src_configure() { + local emesonargs=( + $(meson_use doc gtk_doc) + -Dsystemdsystemunitdir=$(systemd_get_systemunitdir) + ) + meson_src_configure +} + +src_install() { + meson_src_install + + exeinto /etc/init.d/ + newexe "${FILESDIR}/power-profiles-daemon.initd" power-profiles-daemon + + exeinto /etc/conf.d/ + newexe "${FILESDIR}/power-profiles-daemon.confd" power-profiles-daemon + + exeinto /usr/lib/tmpfiles.d/ + newexe "${FILESDIR}/power-profiles-daemon.tmpfiles" power-profiles-daemon.conf +} + +pkg_postinst() { + ewarn "Don't forget to enable \"${PN}\" service, by runnning:" + ewarn "rc-update add ${PN} default && rc-service ${PN} start" +}