From 4c8bae34eceb168ee2551f5dd8ca28af7b39ab98 Mon Sep 17 00:00:00 2001 From: TiagoRG Date: Sat, 21 Oct 2023 14:13:49 +0100 Subject: [PATCH] nvm :skull: Signed-off-by: TiagoRG --- .local/share/gnome-shell/application_state | 46 - .../extension.js | 35 - .../metadata.json | 15 - .../prefs.js | 111 - .../schemas/gschemas.compiled | Bin 392 -> 0 bytes ...rg.gnome.shell.extensions.blur.gschema.xml | 20 - .../stylesheet.css | 5 - .../extensions/Vitals@CoreCoding.com/LICENSE | 339 --- .../Vitals@CoreCoding.com/extension.js | 577 ---- .../Vitals@CoreCoding.com/helpers/file.js | 82 - .../icons/battery-symbolic.svg | 8 - .../icons/cpu-symbolic.svg | 1 - .../icons/fan-symbolic.svg | 133 - .../icons/memory-symbolic.svg | 1 - .../icons/network-download-symbolic.svg | 1 - .../icons/network-symbolic.svg | 1 - .../icons/network-upload-symbolic.svg | 1 - .../icons/storage-symbolic.svg | 3 - .../icons/system-symbolic.svg | 3 - .../icons/temperature-symbolic.svg | 45 - .../icons/voltage-symbolic.svg | 125 - .../locale/ca/LC_MESSAGES/vitals.mo | Bin 3343 -> 0 bytes .../locale/cs/LC_MESSAGES/vitals.mo | Bin 8345 -> 0 bytes .../locale/de/LC_MESSAGES/vitals.mo | Bin 8159 -> 0 bytes .../locale/es/LC_MESSAGES/vitals.mo | Bin 3298 -> 0 bytes .../locale/fi_FI/LC_MESSAGES/vitals.mo | Bin 4004 -> 0 bytes .../locale/fr/LC_MESSAGES/vitals.mo | Bin 7288 -> 0 bytes .../locale/it/LC_MESSAGES/vitals.mo | Bin 3030 -> 0 bytes .../locale/nl/LC_MESSAGES/vitals.mo | Bin 6939 -> 0 bytes .../locale/oc/LC_MESSAGES/vitals.mo | Bin 3817 -> 0 bytes .../locale/pl/LC_MESSAGES/vitals.mo | Bin 3501 -> 0 bytes .../locale/pt/LC_MESSAGES/vitals.mo | Bin 3935 -> 0 bytes .../locale/pt_BR/LC_MESSAGES/vitals.mo | Bin 7407 -> 0 bytes .../locale/ru/LC_MESSAGES/vitals.mo | Bin 10711 -> 0 bytes .../locale/sk/LC_MESSAGES/vitals.mo | Bin 8559 -> 0 bytes .../locale/tr/LC_MESSAGES/vitals.mo | Bin 8416 -> 0 bytes .../locale/uk/LC_MESSAGES/vitals.mo | Bin 10967 -> 0 bytes .../locale/zh_CN/LC_MESSAGES/vitals.mo | Bin 7900 -> 0 bytes .../Vitals@CoreCoding.com/menuItem.js | 77 - .../Vitals@CoreCoding.com/metadata.json | 13 - .../extensions/Vitals@CoreCoding.com/prefs.js | 137 - .../extensions/Vitals@CoreCoding.com/prefs.ui | 1211 --------- .../schemas/gschemas.compiled | Bin 1780 -> 0 bytes ....gnome.shell.extensions.vitals.gschema.xml | 140 - .../Vitals@CoreCoding.com/sensors.js | 671 ----- .../Vitals@CoreCoding.com/stylesheet.css | 16 - .../Vitals@CoreCoding.com/values.js | 337 --- .../appIndicator.js | 1571 ----------- .../dbusMenu.js | 950 ------- .../dbusProxy.js | 103 - .../extension.js | 89 - .../iconCache.js | 179 -- .../indicatorStatusIcon.js | 592 ----- .../interfaces-xml/DBusMenu.xml | 66 - .../interfaces-xml/StatusNotifierItem.xml | 130 - .../interfaces-xml/StatusNotifierWatcher.xml | 38 - .../interfaces.js | 52 - .../cs/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2225 -> 0 bytes .../de/LC_MESSAGES/AppIndicatorExtension.mo | Bin 949 -> 0 bytes .../fr/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2377 -> 0 bytes .../hu/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2434 -> 0 bytes .../it/LC_MESSAGES/AppIndicatorExtension.mo | Bin 1039 -> 0 bytes .../ja/LC_MESSAGES/AppIndicatorExtension.mo | Bin 972 -> 0 bytes .../ko/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2373 -> 0 bytes .../nl/LC_MESSAGES/AppIndicatorExtension.mo | Bin 1024 -> 0 bytes .../oc/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2334 -> 0 bytes .../pl/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2451 -> 0 bytes .../LC_MESSAGES/AppIndicatorExtension.mo | Bin 1067 -> 0 bytes .../ru/LC_MESSAGES/AppIndicatorExtension.mo | Bin 3067 -> 0 bytes .../sk/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2239 -> 0 bytes .../sr/LC_MESSAGES/AppIndicatorExtension.mo | Bin 1132 -> 0 bytes .../LC_MESSAGES/AppIndicatorExtension.mo | Bin 1020 -> 0 bytes .../ta/LC_MESSAGES/AppIndicatorExtension.mo | Bin 3523 -> 0 bytes .../tr/LC_MESSAGES/AppIndicatorExtension.mo | Bin 2497 -> 0 bytes .../LC_MESSAGES/AppIndicatorExtension.mo | Bin 2338 -> 0 bytes .../metadata.json | 13 - .../pixmapsUtils.js | 68 - .../prefs.js | 326 --- .../promiseUtils.js | 324 --- .../schemas/gschemas.compiled | Bin 820 -> 0 bytes ....shell.extensions.appindicator.gschema.xml | 49 - .../settingsManager.js | 55 - .../statusNotifierWatcher.js | 287 -- .../trayIconsManager.js | 104 - .../util.js | 434 --- .../components/appfolders.js | 262 -- .../components/applications.js | 548 ---- .../components/dash_to_dock.js | 322 --- .../components/lockscreen.js | 167 -- .../components/overview.js | 309 --- .../blur-my-shell@aunetx/components/panel.js | 695 ----- .../components/screenshot.js | 173 -- .../components/window_list.js | 162 -- .../conveniences/connections.js | 101 - .../conveniences/effects_manager.js | 89 - .../blur-my-shell@aunetx/conveniences/keys.js | 131 - .../conveniences/settings.js | 182 -- .../blur-my-shell@aunetx/dbus/client.js | 58 - .../blur-my-shell@aunetx/dbus/iface.xml | 12 - .../blur-my-shell@aunetx/dbus/services.js | 90 - .../effects/color_effect.glsl | 13 - .../effects/color_effect.js | 181 -- .../effects/noise_effect.glsl | 20 - .../effects/noise_effect.js | 109 - .../effects/paint_signals.js | 89 - .../blur-my-shell@aunetx/extension.js | 641 ----- .../scalable/actions/add-window-symbolic.svg | 4 - .../actions/applications-symbolic.svg | 56 - .../actions/bottom-panel-symbolic.svg | 44 - .../scalable/actions/dash-symbolic.svg | 44 - .../scalable/actions/general-symbolic.svg | 64 - .../actions/heart-filled-symbolic.svg | 40 - .../scalable/actions/other-symbolic.svg | 1 - .../scalable/actions/overview-symbolic.svg | 56 - .../actions/remove-window-symbolic.svg | 3 - .../scalable/actions/reset-symbolic.svg | 7 - .../scalable/actions/select-mode-symbolic.svg | 2 - .../actions/select-window-symbolic.svg | 2 - .../locale/ar/LC_MESSAGES/blur-my-shell.mo | Bin 12893 -> 0 bytes .../locale/az/LC_MESSAGES/blur-my-shell.mo | Bin 1089 -> 0 bytes .../locale/bg/LC_MESSAGES/blur-my-shell.mo | Bin 4362 -> 0 bytes .../locale/ca/LC_MESSAGES/blur-my-shell.mo | Bin 1402 -> 0 bytes .../locale/cs/LC_MESSAGES/blur-my-shell.mo | Bin 11360 -> 0 bytes .../locale/de/LC_MESSAGES/blur-my-shell.mo | Bin 11858 -> 0 bytes .../locale/el/LC_MESSAGES/blur-my-shell.mo | Bin 15185 -> 0 bytes .../locale/es/LC_MESSAGES/blur-my-shell.mo | Bin 11744 -> 0 bytes .../locale/fr/LC_MESSAGES/blur-my-shell.mo | Bin 11908 -> 0 bytes .../locale/he/LC_MESSAGES/blur-my-shell.mo | Bin 661 -> 0 bytes .../locale/hu/LC_MESSAGES/blur-my-shell.mo | Bin 11464 -> 0 bytes .../locale/it/LC_MESSAGES/blur-my-shell.mo | Bin 11739 -> 0 bytes .../locale/ka/LC_MESSAGES/blur-my-shell.mo | Bin 3077 -> 0 bytes .../locale/ko/LC_MESSAGES/blur-my-shell.mo | Bin 4499 -> 0 bytes .../locale/nb_NO/LC_MESSAGES/blur-my-shell.mo | Bin 3908 -> 0 bytes .../locale/nl/LC_MESSAGES/blur-my-shell.mo | Bin 11469 -> 0 bytes .../locale/nn/LC_MESSAGES/blur-my-shell.mo | Bin 1639 -> 0 bytes .../locale/pl/LC_MESSAGES/blur-my-shell.mo | Bin 11370 -> 0 bytes .../locale/pt/LC_MESSAGES/blur-my-shell.mo | Bin 11087 -> 0 bytes .../locale/pt_BR/LC_MESSAGES/blur-my-shell.mo | Bin 11531 -> 0 bytes .../locale/ru/LC_MESSAGES/blur-my-shell.mo | Bin 14926 -> 0 bytes .../locale/sl/LC_MESSAGES/blur-my-shell.mo | Bin 11134 -> 0 bytes .../locale/sv/LC_MESSAGES/blur-my-shell.mo | Bin 11310 -> 0 bytes .../locale/ta/LC_MESSAGES/blur-my-shell.mo | Bin 19778 -> 0 bytes .../locale/tr/LC_MESSAGES/blur-my-shell.mo | Bin 11767 -> 0 bytes .../locale/uk/LC_MESSAGES/blur-my-shell.mo | Bin 13909 -> 0 bytes .../locale/vi/LC_MESSAGES/blur-my-shell.mo | Bin 7854 -> 0 bytes .../zh_Hans/LC_MESSAGES/blur-my-shell.mo | Bin 10394 -> 0 bytes .../blur-my-shell@aunetx/metadata.json | 20 - .../preferences/applications.js | 174 -- .../preferences/customize_row.js | 163 -- .../blur-my-shell@aunetx/preferences/dash.js | 43 - .../preferences/general.js | 49 - .../blur-my-shell@aunetx/preferences/menu.js | 67 - .../blur-my-shell@aunetx/preferences/other.js | 49 - .../preferences/overview.js | 47 - .../blur-my-shell@aunetx/preferences/panel.js | 65 - .../preferences/window_row.js | 109 - .../extensions/blur-my-shell@aunetx/prefs.js | 41 - .../schemas/gschemas.compiled | Bin 8160 -> 0 bytes ...shell.extensions.blur-my-shell.gschema.xml | 467 ---- .../blur-my-shell@aunetx/stylesheet.css | 334 --- .../blur-my-shell@aunetx/ui/applications.ui | 163 -- .../blur-my-shell@aunetx/ui/customize-row.ui | 143 - .../blur-my-shell@aunetx/ui/dash.ui | 73 - .../blur-my-shell@aunetx/ui/general.ui | 234 -- .../blur-my-shell@aunetx/ui/menu.ui | 37 - .../blur-my-shell@aunetx/ui/other.ui | 62 - .../blur-my-shell@aunetx/ui/overview.ui | 94 - .../blur-my-shell@aunetx/ui/panel.ui | 141 - .../blur-my-shell@aunetx/ui/window-row.ui | 43 - .../caffeine@patapon.info/extension.js | 1128 -------- .../caffeine-infinite-timer-symbolic.svg | 37 - .../icons/caffeine-long-timer-symbolic.svg | 50 - .../icons/caffeine-medium-timer-symbolic.svg | 50 - .../icons/caffeine-short-timer-symbolic.svg | 3 - .../actions/applications-symbolic.svg | 56 - .../scalable/actions/general-symbolic.svg | 64 - .../icons/my-caffeine-off-symbolic.svg | 182 -- .../icons/my-caffeine-on-symbolic.svg | 182 -- .../icons/stopwatch-symbolic.svg | 2 - .../gnome-shell-extension-caffeine.mo | Bin 6692 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 5649 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 5535 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 2177 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 6634 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 6672 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 6513 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 1670 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 3029 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 5998 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 965 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 4403 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 985 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 8503 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 6157 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 1343 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 6353 -> 0 bytes .../gnome-shell-extension-caffeine.mo | Bin 5870 -> 0 bytes .../caffeine@patapon.info/metadata.json | 20 - .../preferences/appsPage.js | 220 -- .../preferences/displayPage.js | 138 - .../preferences/generalPage.js | 387 --- .../extensions/caffeine@patapon.info/prefs.js | 84 - .../schemas/gschemas.compiled | Bin 1612 -> 0 bytes ...nome.shell.extensions.caffeine.gschema.xml | 116 - .../LICENSE.rst | 24 - .../README.rst | 84 - .../confirmDialog.js | 72 - .../constants.js | 23 - .../extension.js | 1134 -------- .../keyboard.js | 41 - .../ar/LC_MESSAGES/clipboard-indicator.mo | Bin 2308 -> 0 bytes .../ca/LC_MESSAGES/clipboard-indicator.mo | Bin 1584 -> 0 bytes .../cs/LC_MESSAGES/clipboard-indicator.mo | Bin 2125 -> 0 bytes .../de/LC_MESSAGES/clipboard-indicator.mo | Bin 2185 -> 0 bytes .../el/LC_MESSAGES/clipboard-indicator.mo | Bin 1266 -> 0 bytes .../es/LC_MESSAGES/clipboard-indicator.mo | Bin 2224 -> 0 bytes .../eu/LC_MESSAGES/clipboard-indicator.mo | Bin 2031 -> 0 bytes .../fa/LC_MESSAGES/clipboard-indicator.mo | Bin 2412 -> 0 bytes .../fi/LC_MESSAGES/clipboard-indicator.mo | Bin 1092 -> 0 bytes .../fr_FR/LC_MESSAGES/clipboard-indicator.mo | Bin 1971 -> 0 bytes .../hu/LC_MESSAGES/clipboard-indicator.mo | Bin 2127 -> 0 bytes .../it/LC_MESSAGES/clipboard-indicator.mo | Bin 2047 -> 0 bytes .../locale/ja/LC_MESSAGES/ja.mo | Bin 2191 -> 0 bytes .../nl/LC_MESSAGES/clipboard-indicator.mo | Bin 2061 -> 0 bytes .../oc/LC_MESSAGES/clipboard-indicator.mo | Bin 2102 -> 0 bytes .../pl/LC_MESSAGES/clipboard-indicator.mo | Bin 1471 -> 0 bytes .../pt_BR/LC_MESSAGES/clipboard-indicator.mo | Bin 2201 -> 0 bytes .../ru/LC_MESSAGES/clipboard-indicator.mo | Bin 2626 -> 0 bytes .../sk/LC_MESSAGES/clipboard-indicator.mo | Bin 1822 -> 0 bytes .../tr/LC_MESSAGES/clipboard-indicator.mo | Bin 2050 -> 0 bytes .../uk/LC_MESSAGES/clipboard-indicator.mo | Bin 4393 -> 0 bytes .../zh_CN/LC_MESSAGES/clipboard-indicator.mo | Bin 2011 -> 0 bytes .../metadata.json | 13 - .../clipboard-indicator@tudmotu.com/prefs.js | 273 -- .../registry.js | 281 -- .../schemas/gschemas.compiled | Bin 1612 -> 0 bytes ...extensions.clipboard-indicator.gschema.xml | 165 -- .../stylesheet.css | 71 - .../extensions/color-picker@tuberry/color.js | 187 -- .../extensions/color-picker@tuberry/const.js | 25 - .../color-picker@tuberry/extension.js | 654 ----- .../extensions/color-picker@tuberry/fubar.js | 102 - .../gnome-shell-extension-color-picker.mo | Bin 1111 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 1187 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 936 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 1164 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 1801 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 1153 -> 0 bytes .../gnome-shell-extension-color-picker.mo | Bin 1943 -> 0 bytes .../extensions/color-picker@tuberry/menu.js | 156 -- .../color-picker@tuberry/metadata.json | 13 - .../extensions/color-picker@tuberry/prefs.js | 99 - .../schemas/gschemas.compiled | Bin 1323 -> 0 bytes ....shell.extensions.color-picker.gschema.xml | 81 - .../color-picker@tuberry/stylesheet.css | 21 - .../extensions/color-picker@tuberry/ui.js | 505 ---- .../extensions/color-picker@tuberry/util.js | 65 - .../dash-to-panel@jderose9.github.com/COPYING | 341 --- .../README.md | 194 -- .../appIcons.js | 1886 ------------- .../desktopIconsIntegration.js | 160 -- .../extension.js | 141 - .../img/highlight_stacked_bg.svg | 7 - .../img/highlight_stacked_bg_2.svg | 7 - .../img/highlight_stacked_bg_3.svg | 7 - .../intellihide.js | 426 --- .../locale/cs/LC_MESSAGES/dash-to-panel.mo | Bin 16769 -> 0 bytes .../locale/de/LC_MESSAGES/dash-to-panel.mo | Bin 21295 -> 0 bytes .../locale/es/LC_MESSAGES/dash-to-panel.mo | Bin 21553 -> 0 bytes .../locale/fa/LC_MESSAGES/dash-to-panel.mo | Bin 19898 -> 0 bytes .../locale/fr/LC_MESSAGES/dash-to-panel.mo | Bin 26064 -> 0 bytes .../locale/gl/LC_MESSAGES/dash-to-panel.mo | Bin 18062 -> 0 bytes .../locale/hu/LC_MESSAGES/dash-to-panel.mo | Bin 22960 -> 0 bytes .../locale/it/LC_MESSAGES/dash-to-panel.mo | Bin 19582 -> 0 bytes .../locale/ja/LC_MESSAGES/dash-to-panel.mo | Bin 23380 -> 0 bytes .../locale/kk/LC_MESSAGES/dash-to-panel.mo | Bin 10823 -> 0 bytes .../locale/ko/LC_MESSAGES/dash-to-panel.mo | Bin 21724 -> 0 bytes .../locale/nl/LC_MESSAGES/dash-to-panel.mo | Bin 17138 -> 0 bytes .../locale/pl/LC_MESSAGES/dash-to-panel.mo | Bin 17380 -> 0 bytes .../locale/pt_BR/LC_MESSAGES/dash-to-panel.mo | Bin 16495 -> 0 bytes .../locale/ru/LC_MESSAGES/dash-to-panel.mo | Bin 26950 -> 0 bytes .../locale/sk/LC_MESSAGES/dash-to-panel.mo | Bin 21075 -> 0 bytes .../locale/sv/LC_MESSAGES/dash-to-panel.mo | Bin 17499 -> 0 bytes .../locale/tr/LC_MESSAGES/dash-to-panel.mo | Bin 22118 -> 0 bytes .../locale/uk/LC_MESSAGES/dash-to-panel.mo | Bin 6875 -> 0 bytes .../locale/zh_CN/LC_MESSAGES/dash-to-panel.mo | Bin 19556 -> 0 bytes .../locale/zh_TW/LC_MESSAGES/dash-to-panel.mo | Bin 14647 -> 0 bytes .../metadata.json | 13 - .../overview.js | 518 ---- .../panel.js | 1258 --------- .../panelManager.js | 771 ------ .../panelPositions.js | 61 - .../panelSettings.js | 111 - .../panelStyle.js | 314 --- .../prefs.js | 2336 ---------------- .../progress.js | 597 ----- .../proximity.js | 256 -- .../schemas/gschemas.compiled | Bin 17244 -> 0 bytes ...shell.extensions.dash-to-panel.gschema.xml | 1273 --------- .../stylesheet.css | 156 -- .../taskbar.js | 1570 ----------- .../transparency.js | 252 -- .../ui/BoxAdvancedOptions.ui | 28 - .../ui/BoxAnimateAppIconHoverOptions.ui | 189 -- .../ui/BoxDotOptions.ui | 271 -- .../ui/BoxDynamicOpacityOptions.ui | 100 - .../ui/BoxGroupAppsOptions.ui | 153 -- .../ui/BoxIntellihideOptions.ui | 226 -- .../ui/BoxMiddleClickOptions.ui | 100 - .../ui/BoxOverlayShortcut.ui | 115 - .../ui/BoxScrollIconOptions.ui | 44 - .../ui/BoxScrollPanelOptions.ui | 56 - .../ui/BoxSecondaryMenuOptions.ui | 43 - .../ui/BoxShowApplicationsOptions.ui | 86 - .../ui/BoxShowDesktopOptions.ui | 125 - .../ui/BoxWindowPreviewOptions.ui | 484 ---- .../ui/SettingsAbout.ui | 99 - .../ui/SettingsAction.ui | 165 -- .../ui/SettingsBehavior.ui | 192 -- .../ui/SettingsFineTune.ui | 279 -- .../ui/SettingsPosition.ui | 243 -- .../ui/SettingsStyle.ui | 345 --- .../utils.js | 883 ------ .../windowPreview.js | 1152 -------- .../ding@rastersoft.com/app/askRenamePopup.js | 120 - .../ding@rastersoft.com/app/autoAr.js | 774 ------ .../app/createThumbnail.js | 65 - .../ding@rastersoft.com/app/dbusInterfaces.js | 225 -- .../ding@rastersoft.com/app/dbusUtils.js | 1012 ------- .../ding@rastersoft.com/app/desktopGrid.js | 587 ---- .../app/desktopIconItem.js | 787 ------ .../app/desktopIconsUtil.js | 356 --- .../ding@rastersoft.com/app/desktopManager.js | 2367 ----------------- .../ding@rastersoft.com/app/ding.js | 213 -- .../ding@rastersoft.com/app/enums.js | 109 - .../ding@rastersoft.com/app/fileItem.js | 796 ------ .../ding@rastersoft.com/app/fileItemMenu.js | 545 ---- .../ding@rastersoft.com/app/fileUtils.js | 106 - .../app/notifyX11UnderWayland.js | 58 - .../ding@rastersoft.com/app/preferences.js | 162 -- .../ding@rastersoft.com/app/prefswindow.js | 215 -- .../ding@rastersoft.com/app/promiseUtils.js | 80 - .../ding@rastersoft.com/app/showErrorPopup.js | 65 - .../ding@rastersoft.com/app/stackItem.js | 124 - .../ding@rastersoft.com/app/stylesheet.css | 30 - .../app/templatesScriptsManager.js | 213 -- .../ding@rastersoft.com/app/thumbnails.js | 178 -- .../emulateX11WindowType.js | 376 --- .../ding@rastersoft.com/extension.js | 617 ----- .../ding@rastersoft.com/gnomeShellOverride.js | 147 - .../locale/be/LC_MESSAGES/ding.mo | Bin 19373 -> 0 bytes .../locale/ca/LC_MESSAGES/ding.mo | Bin 16248 -> 0 bytes .../locale/cs/LC_MESSAGES/ding.mo | Bin 14996 -> 0 bytes .../locale/da/LC_MESSAGES/ding.mo | Bin 2650 -> 0 bytes .../locale/de/LC_MESSAGES/ding.mo | Bin 8806 -> 0 bytes .../locale/es/LC_MESSAGES/ding.mo | Bin 15136 -> 0 bytes .../locale/fi/LC_MESSAGES/ding.mo | Bin 12290 -> 0 bytes .../locale/fr/LC_MESSAGES/ding.mo | Bin 16089 -> 0 bytes .../locale/fur/LC_MESSAGES/ding.mo | Bin 2715 -> 0 bytes .../locale/he/LC_MESSAGES/ding.mo | Bin 3649 -> 0 bytes .../locale/hr/LC_MESSAGES/ding.mo | Bin 2788 -> 0 bytes .../locale/hu/LC_MESSAGES/ding.mo | Bin 7163 -> 0 bytes .../locale/id/LC_MESSAGES/ding.mo | Bin 2719 -> 0 bytes .../locale/it/LC_MESSAGES/ding.mo | Bin 9316 -> 0 bytes .../locale/ja/LC_MESSAGES/ding.mo | Bin 16280 -> 0 bytes .../locale/ko/LC_MESSAGES/ding.mo | Bin 12592 -> 0 bytes .../locale/nl/LC_MESSAGES/ding.mo | Bin 2858 -> 0 bytes .../locale/oc/LC_MESSAGES/ding.mo | Bin 15486 -> 0 bytes .../locale/pl/LC_MESSAGES/ding.mo | Bin 15081 -> 0 bytes .../locale/pt_BR/LC_MESSAGES/ding.mo | Bin 7573 -> 0 bytes .../locale/ro/LC_MESSAGES/ding.mo | Bin 8856 -> 0 bytes .../locale/ru/LC_MESSAGES/ding.mo | Bin 19747 -> 0 bytes .../locale/sk/LC_MESSAGES/ding.mo | Bin 9109 -> 0 bytes .../locale/sv/LC_MESSAGES/ding.mo | Bin 9956 -> 0 bytes .../locale/tr/LC_MESSAGES/ding.mo | Bin 14894 -> 0 bytes .../locale/uk/LC_MESSAGES/ding.mo | Bin 19334 -> 0 bytes .../locale/zh_CN/LC_MESSAGES/ding.mo | Bin 11226 -> 0 bytes .../locale/zh_TW/LC_MESSAGES/ding.mo | Bin 5963 -> 0 bytes .../ding@rastersoft.com/metadata.json | 11 - .../extensions/ding@rastersoft.com/prefs.js | 39 - .../schemas/gschemas.compiled | Bin 1445 -> 0 bytes ...rg.gnome.shell.extensions.ding.gschema.xml | 109 - .../ding@rastersoft.com/visibleArea.js | 146 - .../extension.js | 68 - .../metadata.json | 11 - .../LICENSE | 674 ----- .../extension.js | 209 -- .../libs/libpanel/LICENSE | 674 ----- .../libs/libpanel/README.md | 1 - .../libs/libpanel/gschemas.compiled | Bin 632 -> 0 bytes .../libs/libpanel/main.js | 953 ------- .../libs/libpanel/patcher.js | 60 - .../libs/libpanel/utils.js | 232 -- .../libs/widgets.js | 220 -- ...k-settings-audio-panel@rayzeq.github.io.mo | Bin 3552 -> 0 bytes ...k-settings-audio-panel@rayzeq.github.io.mo | Bin 4186 -> 0 bytes ...k-settings-audio-panel@rayzeq.github.io.mo | Bin 3597 -> 0 bytes .../metadata.json | 13 - .../prefs.js | 320 --- .../schemas/gschemas.compiled | Bin 964 -> 0 bytes ...ons.quick-settings-audio-panel.gschema.xml | 48 - .../stylesheet.css | 62 - .../extension.js | 362 --- .../tiling-assistant@leleat-on-github.mo | Bin 1601 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 8980 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 14147 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 10972 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 14373 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 13897 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 5781 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 5568 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 8740 -> 0 bytes .../tiling-assistant@leleat-on-github.mo | Bin 1189 -> 0 bytes .../media/insert-link-symbolic.svg | 46 - .../preferences-desktop-apps-symbolic.svg | 1 - .../metadata.json | 13 - .../prefs.js | 304 --- .../schemas/gschemas.compiled | Bin 5813 -> 0 bytes ...ll.extensions.tiling-assistant.gschema.xml | 287 -- .../src/common.js | 423 --- .../src/dependencies/gi.js | 9 - .../src/dependencies/prefs.js | 4 - .../src/dependencies/prefs/gi.js | 6 - .../src/dependencies/shell.js | 11 - .../src/dependencies/unexported/altTab.js | 16 - .../dependencies/unexported/windowManager.js | 1 - .../src/extension/activeWindowHint.js | 333 --- .../src/extension/altTab.js | 486 ---- .../src/extension/keybindingHandler.js | 553 ---- .../src/extension/layoutsManager.js | 559 ---- .../src/extension/moveHandler.js | 902 ------- .../src/extension/resizeHandler.js | 534 ---- .../src/extension/tileEditingMode.js | 774 ------ .../src/extension/tilingPopup.js | 352 --- .../src/extension/tilingWindowManager.js | 1339 ---------- .../src/extension/utility.js | 789 ------ .../src/layouts_example.json | 112 - .../src/prefs/layoutRow.js | 221 -- .../src/prefs/layoutRowEntry.js | 124 - .../src/prefs/layoutsPrefs.js | 222 -- .../src/prefs/shortcutListener.js | 208 -- .../src/ui/layoutRow.ui | 135 - .../src/ui/layoutRowEntry.ui | 40 - .../src/ui/prefs.ui | 1139 -------- .../src/ui/shortcutListener.ui | 31 - .../stylesheet.css | 8 - .local/share/gnome-shell/update-check-45 | 0 447 files changed, 66241 deletions(-) delete mode 100644 .local/share/gnome-shell/application_state delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/extension.js delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.blur.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/LICENSE delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/file.js delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/cs/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/de/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/es/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/fr/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/nl/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/zh_CN/LC_MESSAGES/vitals.mo delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/menuItem.js delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/fr/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/hu/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/it/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ru/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sk/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr@latin/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/tr/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js delete mode 100644 .local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/connections.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/settings.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/client.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/iface.xml delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.glsl delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/paint_signals.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell.mo delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/applications.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/customize_row.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/general.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/menu.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/other.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/overview.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/customize-row.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/general.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/menu.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/other.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/overview.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui delete mode 100644 .local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/extension.js delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-infinite-timer-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-long-timer-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-medium-timer-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-short-timer-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/applications-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/general-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-off-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-on-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/icons/stopwatch-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ca/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/cs/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/de/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/es/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/fr/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/hu/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/it_IT/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ja/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ko/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/nl/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/pl/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/pr_BR/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/pt_PT/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ru/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/sk/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/sv/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/tr/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-caffeine.mo delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/appsPage.js delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/displayPage.js delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/generalPage.js delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/org.gnome.shell.extensions.caffeine.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/LICENSE.rst delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/README.rst delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/confirmDialog.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/constants.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/keyboard.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ar/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ca/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/cs/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/de/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/el/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/es/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/eu/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fa/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fi/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fr_FR/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/hu/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/it/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ja/LC_MESSAGES/ja.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/nl/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/oc/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pl/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pt_BR/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ru/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/sk/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/tr/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/uk/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/zh_CN/LC_MESSAGES/clipboard-indicator.mo delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/registry.js delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/org.gnome.shell.extensions.clipboard-indicator.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/color.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/const.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/extension.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/fubar.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/de_DE/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/es_ES/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/it_IT/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/nl/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/pt_PT/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/tr_TR/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-color-picker.mo delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/menu.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/schemas/org.gnome.shell.extensions.color-picker.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/ui.js delete mode 100644 .local/share/gnome-shell/extensions/color-picker@tuberry/util.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/COPYING delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/README.md delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/appIcons.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/desktopIconsIntegration.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg.svg delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_2.svg delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_3.svg delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/intellihide.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/cs/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/de/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/es/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fa/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fr/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/gl/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/hu/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/it/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ja/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/kk/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ko/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/nl/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/pl/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/pt_BR/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ru/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/sk/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/sv/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/tr/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/uk/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/zh_CN/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/zh_TW/LC_MESSAGES/dash-to-panel.mo delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/overview.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panel.js delete mode 100755 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelManager.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelPositions.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelSettings.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelStyle.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/progress.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/proximity.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/taskbar.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/transparency.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAdvancedOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAnimateAppIconHoverOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDotOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDynamicOpacityOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxGroupAppsOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxIntellihideOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxMiddleClickOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxOverlayShortcut.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollIconOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollPanelOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxSecondaryMenuOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowApplicationsOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowDesktopOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxWindowPreviewOptions.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAbout.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAction.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsBehavior.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsFineTune.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsPosition.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsStyle.ui delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/utils.js delete mode 100644 .local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/windowPreview.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/askRenamePopup.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/autoAr.js delete mode 100755 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/createThumbnail.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusInterfaces.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusUtils.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopGrid.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconItem.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconsUtil.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopManager.js delete mode 100755 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/ding.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/enums.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItem.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItemMenu.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileUtils.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/notifyX11UnderWayland.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/preferences.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/prefswindow.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/promiseUtils.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/showErrorPopup.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/stackItem.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/templatesScriptsManager.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/app/thumbnails.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/emulateX11WindowType.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/gnomeShellOverride.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/be/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ca/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/cs/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/da/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/de/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/es/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fi/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fr/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fur/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/he/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/hr/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/hu/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/id/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/it/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ja/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ko/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/nl/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/oc/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/pl/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/pt_BR/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ro/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ru/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sk/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sv/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/tr/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/uk/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_CN/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_TW/LC_MESSAGES/ding.mo delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/org.gnome.shell.extensions.ding.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/ding@rastersoft.com/visibleArea.js delete mode 100644 .local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/extension.js delete mode 100644 .local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/LICENSE delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/extension.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/LICENSE delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/README.md delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/main.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/patcher.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/utils.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/widgets.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/cs/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/fr_FR/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/nl/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/org.gnome.shell.extensions.quick-settings-audio-panel.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/stylesheet.css delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/extension.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/cs/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/de_CH/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/de_DE/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/es/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/hu/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/it_IT/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/ja/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/nl/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/pt_BR/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/zh_TW/LC_MESSAGES/tiling-assistant@leleat-on-github.mo delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/insert-link-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/preferences-desktop-apps-symbolic.svg delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/metadata.json delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/schemas/gschemas.compiled delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/schemas/org.gnome.shell.extensions.tiling-assistant.gschema.xml delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/common.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/gi.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs/gi.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/shell.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/altTab.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/windowManager.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/activeWindowHint.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/altTab.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/layoutsManager.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/moveHandler.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingPopup.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/utility.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/layouts_example.json delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRow.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutsPrefs.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRow.ui delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRowEntry.ui delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/prefs.ui delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui delete mode 100644 .local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/stylesheet.css delete mode 100644 .local/share/gnome-shell/update-check-45 diff --git a/.local/share/gnome-shell/application_state b/.local/share/gnome-shell/application_state deleted file mode 100644 index 3ab97eb..0000000 --- a/.local/share/gnome-shell/application_state +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/extension.js b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/extension.js deleted file mode 100644 index dd535a1..0000000 --- a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/extension.js +++ /dev/null @@ -1,35 +0,0 @@ -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -export default class ControlBlurExtension extends Extension { - enable() { - this._settings = this.getSettings(); - this._dialog = Main.screenShield._dialog; - if (this._dialog) - this._dialog._updateBackgroundEffects = this._myEffects(); - } - - _myEffects() { - const themeContext = St.ThemeContext.get_for_stage(global.stage); - - for (const widget of this._dialog._backgroundGroup) { - const effect = widget.get_effect('blur'); - - if (effect) { - effect.set({ - brightness: this._settings.get_double('brightness'), - sigma: this._settings.get_int('sigma') * themeContext.scale_factor, - }); - } - } - } - - // unlock-dialog is used in session-modes because this extension purpose is - // to tweak blur effect on lock screen itself. - disable() { - this._dialog = null; - this._settings = null; - } -} diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/metadata.json b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/metadata.json deleted file mode 100644 index f20ebd6..0000000 --- a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/metadata.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Control the Blur Effect On Lock Screen.", - "name": "Control Blur Effect On Lock Screen", - "session-modes": [ - "unlock-dialog" - ], - "settings-schema": "org.gnome.shell.extensions.blur", - "shell-version": [ - "45" - ], - "url": "https://github.com/PRATAP-KUMAR/Control_Blur_Effect_On_Lock_Screen", - "uuid": "ControlBlurEffectOnLockScreen@pratap.fastmail.fm", - "version": 24 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/prefs.js b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/prefs.js deleted file mode 100644 index 1450e86..0000000 --- a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/prefs.js +++ /dev/null @@ -1,111 +0,0 @@ -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; - -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class ControlBlurExtensionPreferences extends ExtensionPreferences { - fillPreferencesWindow(window) { - window._settings = this.getSettings(); - - const adjustBlur = () => { - let hbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5}); - let blurLabel = new Gtk.Label({label: 'Adjust Sigma', xalign: 0, hexpand: true}); - - this.blur_adjustment = new Gtk.Adjustment({ - lower: 0, - 'step-increment': 1, - 'page-increment': 10, - upper: 999, - }); - - this.blur_scale = new Gtk.Scale({ - hexpand: true, - margin_start: 20, - visible: true, - 'draw-value': true, - 'value-pos': 'left', - 'can-focus': true, - digits: 0, - adjustment: this.blur_adjustment, - }); - - this.resetBlurButton = new Gtk.Button({margin_start: 5}); - this.resetBlurButton.set_label("Reset to Extensions's Default Value"); - this.resetBlurButton.connect('clicked', () => { - window._settings.set_int('sigma', 1); - this.blur_scale.set_value(window._settings.get_int('sigma')); - }); - - this.blur_scale.set_value(window._settings.get_int('sigma')); - this.blur_scale.connect('value-changed', entry => { - window._settings.set_int('sigma', entry.get_value()); - }); - - hbox.append(blurLabel); - hbox.append(this.blur_scale); - hbox.append(this.resetBlurButton); - - return hbox; - }; - - const adjustBrightness = () => { - let hbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, margin_top: 5}); - let brightnessLabel = new Gtk.Label({label: 'Adjust Brightness', xalign: 0, hexpand: true}); - - this.brightness_adjustment = new Gtk.Adjustment({ - lower: 0, - 'step-increment': 0.05, - 'page-increment': 0.1, - upper: 1, - }); - - this.brightness_scale = new Gtk.Scale({ - hexpand: true, - margin_start: 20, - visible: true, - 'draw-value': true, - 'value-pos': 'left', - 'can-focus': true, - digits: 2, - adjustment: this.brightness_adjustment, - }); - - this.resetBrightnessButton = new Gtk.Button({margin_start: 5}); - this.resetBrightnessButton.set_label("Reset to Extensions's Default Value"); - this.resetBrightnessButton.connect('clicked', () => { - window._settings.set_double('brightness', 0.65); - this.brightness_scale.set_value(window._settings.get_double('brightness')); - }); - - this.brightness_scale.set_value(window._settings.get_double('brightness')); - this.brightness_scale.connect('value-changed', entry => { - window._settings.set_double('brightness', entry.get_value()); - }); - - hbox.append(brightnessLabel); - hbox.append(this.brightness_scale); - hbox.append(this.resetBrightnessButton); - - return hbox; - }; - - const addBoldText = text => { - let txt = new Gtk.Label({xalign: 0, margin_top: 20}); - txt.set_markup(`${text}`); - txt.set_wrap(true); - return txt; - }; - - const page = new Adw.PreferencesPage(); - window.add(page); - - const group = new Adw.PreferencesGroup(); - page.add(group); - - group.add(adjustBlur()); - group.add(adjustBrightness()); - group.add(addBoldText( - 'Please note that when Blur Sigma Value is set to 0, the Brightness will be Maximum Irrespective of the value set above.' - )); - } -} diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/gschemas.compiled deleted file mode 100644 index 98588898989259be7d0f6b25c8397ffb6df1eec6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmYjLJ5Iwu6nuQrkcI}y1riO#T0*+pCo3f2!LnDID{TXuyk5MJ`F0?uG6gSCy*-g1 z;E|7VE>GZRRMVEa^v&4nP}#cHcG_7VT;qct)i*88YMWnxqrAoc_xp!F_r={Zk#A`G zFs$#e=N*}mN1go+^Z}R|^>yA=&fGUkZv) AkpKVy diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.blur.gschema.xml b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.blur.gschema.xml deleted file mode 100644 index 90ae32b..0000000 --- a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/schemas/org.gnome.shell.extensions.blur.gschema.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - 0.65 - Blur Brightness - Controls the Blur Brightness. Value is effective between 0 to 1. Please note that If the "Blur Sigma" value is set to '0', this value will be ignored and shows the lockscreen with max brightness. - - - - - 1 - Blur Sigma - Controls the Blur Sigma. Value is effective between 0 to 100 (But not limited) based on the Background Picture. - Try some thing like 5, 10, 15, 20,... to suit your liking. - - - - diff --git a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/stylesheet.css b/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/stylesheet.css deleted file mode 100644 index d4cfcd8..0000000 --- a/.local/share/gnome-shell/extensions/ControlBlurEffectOnLockScreen@pratap.fastmail.fm/stylesheet.css +++ /dev/null @@ -1,5 +0,0 @@ -/* uncomment below lines and edit the background-color as you wish if you want to change the password-prompt entry field on the lock screen */ - -/* .login-dialog-prompt-entry { - background-color: #000; -} */ \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/LICENSE b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/LICENSE deleted file mode 100644 index d7f1051..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ -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/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js deleted file mode 100644 index ee5d735..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js +++ /dev/null @@ -1,577 +0,0 @@ -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import St from 'gi://St' - -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; - -import * as Sensors from './sensors.js'; - -import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; -import * as Values from './values.js'; -import * as Config from 'resource:///org/gnome/shell/misc/config.js'; -import * as MenuItem from './menuItem.js'; - -let vitalsMenu; - -var VitalsMenuButton = GObject.registerClass({ - GTypeName: 'VitalsMenuButton', -}, class VitalsMenuButton extends PanelMenu.Button { - _init(extensionObject) { - super._init(Clutter.ActorAlign.FILL); - - this._extensionObject = extensionObject; - this._settings = extensionObject.getSettings(); - - 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)); - this._addSettingChangedSignal('menu-centered', 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', 'include-static-info' ]; - 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(this._extensionObject.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').split(" ")); - }); - customButtonBox.add_actor(monitorButton); - - // custom round preferences button - let prefsButton = this._createRoundButton('preferences-system-symbolic', _('Preferences')); - prefsButton.connect('clicked', (self) => { - this.menu._getTopMenu().close(); - this._extensionObject.openPreferences(); - }); - 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 = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - 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 GLib.SOURCE_CONTINUE; - } - ); - } - - _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; - - // keep track of label for removal later - this._hotLabels[key] = label; - - // prevent "called on the widget" "which is not in the stage" errors by adding before width below - this._menuLayout.add_actor(label); - - // support for fixed widths #55, save label (text) width - this._widths[key] = label.width; - } - - _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 existent 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) { - GLib.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(this._extensionObject.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(this._extensionObject.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(this._extensionObject.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; - } - - let centered = this._settings.get_boolean('menu-centered') - - if (centered) arrow_pos = 0.5; - - // 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(); - } -}); - -export default class VitalsExtension extends Extension { - enable() { - vitalsMenu = new VitalsMenuButton(this); - let position = vitalsMenu._positionInPanel(); - Main.panel.addToStatusArea('vitalsMenu', vitalsMenu, position[1], position[0]); - } - - disable() { - vitalsMenu.destroy(); - vitalsMenu = null; - } -} diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/file.js b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/file.js deleted file mode 100644 index a7211b9..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/file.js +++ /dev/null @@ -1,82 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib' - -// convert Uint8Array into a literal string -function convertUint8ArrayToString(contents) { - const decoder = new TextDecoder('utf-8'); - return decoder.decode(contents).trim(); -} - -export 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 = convertUint8ArrayToString(contents); - - // 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/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg deleted file mode 100644 index 70df9ee..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg deleted file mode 100644 index 19969e4..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg deleted file mode 100644 index a584b74..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - - - - Gnome Symbolic Icon Theme - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg deleted file mode 100644 index 13ca4bc..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg deleted file mode 100644 index 5cab840..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg deleted file mode 100644 index 0483417..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg deleted file mode 100644 index e2c5a08..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg deleted file mode 100644 index 9832999..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg deleted file mode 100644 index 909f530..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg deleted file mode 100644 index c58beca..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg +++ /dev/null @@ -1,45 +0,0 @@ - -image/svg+xml \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg deleted file mode 100644 index b2e7eff..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - - - - Gnome Symbolic Icon Theme - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ca/LC_MESSAGES/vitals.mo deleted file mode 100644 index 5a18109cbbec78b561fb686e4b07a33e3380dded..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3343 zcmaKtO^g&p6vs>X()9yW{KBsSg#~41+(ncuF1YNnuyGegc9vjFNNT!kW(s?%+N$c= z9S$D6m~b&M(L|$$3lS5!xF#C(vy)!FN{Sf$P$0#@2v8fj5G`f_H#_hW0<;I<(he5MJ4O zkj8He+yt&gn}am2A0*Qy@G`h7eBXdUH2-dp*0~>~@!P-+U=h3*+z-;Y=fNAmlOT<& z2O1DRHjBqi;LG5x;2Cf|_!f8@_(5oY7QTN2Qd~cW{=Y!7`!7iAtwn>@y9uQE8$q(a z4ZIl~1j+CHffFEpY#I-m_X3DeSq$C{o&xb>ui!!U&wyBpy#|uMZw8(NZ$bNGkmi2@ z()h1J`&)1$+CPN;KS2E06+G5pFRzC7-*AHbTZP9%;4NSuSO97K9+2!l1JXJN1D^%S zujfFD;{-_a1h^melkojRbkewako>s_lHKpXJHa2p&EOS~?5s!fD9(F8imyL#H%Q+{ zL7F!S(!Nwds)H7I7x*f85BMHe^&p-Ud$HThpPTS}6gSzV^FbH+MK&l-%5gt#+H>-g zE}lQT`MeMBJ45?PkaE|%$lu+eu>;(S`w85%zvMglO=oHs?(1<=oR8!F|22q?67I*s zherapg9Y3aH|-_mjdDxZKo|Lw&dXDwjWn@`aZ_z<3w@+ry^C_bg&HGOlX*6hBqkDG z#&}B`qAI;QExD808SB_cOQ=Lt6NxuzMP0H3$~$(z80Xo6wwI2LO6{d(qsB_UHD=>N zvvDbWhNhJ-Wzu=ajpfy>?)LL?B88K@rJVBoX~7#-)`qt|KkyVS4X_g|G zi%hI^y>wi8k+_m_4#u|ZJEZ*Kton3G>?`skhR+IXh4$^8T+XFdIwxaVPBqg+$+)<3 zkwwe-Lb1_^zL+-BE&ImucQVaYjkit4YbMh%_YLKE=435Pifr82rtoasN=XkysG~MJ zBsKDru)`{r{Is-&w?qPe*@TXg41H-o{~*t z+ic2cyU!spbQ2=d)G7I+RjTX5p3fJsR&V)4fanN&6Vb<&=Nh^NNJG@gk0`Az$>aLdkuI~?qz@-lQm?Z z0Xk`0D7|B<-tcT1JFa8LQG>HmYM!Mrw#K2qTa44QB4yKE-@D);1Xe*I2}~V{ylTmX zX2qa%Sob-DM6wx2LCv598(30Wj*^K`j7C#u%#Me!5yB}M`NBk8I4&)HAL4!GqlIIV zO4sPZ7(7GQq;S4aK>@l%Ajv~~T*lI>$nc6)I9V8=>lxN8RHSI;6T0mou6*Cr#MHq> z`vb+t`$i28lZMH53iDph`BIt)rT6lvA*_>rc&0L5*t0l}mPXenvM5oc z7{@UYA`_!TD*d8vu@09B$HC$)nL#whI`dj^m!-zSn}o+G8;t_Z(tJ@K_lsO-Fl`Rm zbE-4XoB8UU_bGrCI&%#PD2sMkB)Piu^-llRODr7W`v?} z@QgtNI=lDlOl7A0?4cdmLg`$WFxvCIoLj-8~yN%Qh-paPd_UY=j5 zR0S&PIQCv;d9piad)k*fx-^GSsZ1owpB6y^@qaRAB^H~Ob*dxe273ToVOU;W3pzMK zf4Gs*Eybo+hSrOATw!l>civrCDYzF6#ysz5KAK-`QbL*743x3}5 zMaZ98;phGEWq2q22K-U@n#=zUlrH`O{sg=Z=~{gc-U0s?%KLZFx$thskHSsl?}eM; z6qNQY_`@)T((gH!KM!TzUw|KiUxz;n{|Md--+(^_{~g{3@BR^`#^4tCAp9hh`twlQ ze+7=fS6%%-LFsqh2bJPa-OCR}YBRhIZih0zN1^Cp3Vs{TK$-8z-Nm}cpww@NGXK3$ z)_Dm27!2Wu;V;3TguekFg0DcC@3*1o?}JQ6^l}fBad$%LZ@=RVWT|Q%%J|Q~dtd|d zrrlpj35q^{4~l;N#IX;hpTBnbZ$at*EhyvuGn9VchGIY8gJNgW zxzw+R>!F4l;iGT^e8$zEhw|R9xcm!H)^`EQd@e(=i&vq{kn4^Q50+P{vz;GM<4l z{}%ii7(7*hw^>~rT$A$?BVwvzXfF<{u5&2 z>JAnuTn|Mbo1yII!%)Vbg73m7py>GolaP6yhBEI@L3ytU#qLumYsxeUWD@gYf$3bn^4C2FDT>RMy1%nT~O9>A4IjP0%g1duKZ~z z^Y@{&Kj-S7clBR${6kmYhccfxAgWQ{fta3p$CcknP?dfAkmGt-A%8!Vac80I=OUEx zo`ur>JQP3sqRU@^GVhn5wEF`n>*_;U=U+k5?;DV(i|A6Goru`qA;d?P5P8lb(%&=4G$PMdM09)% z$q;!kOVvV_k-f+qBF_}EANh=ARy~JTrH_z)5cxS*wq;e_11=po%342(h%V&WhI|Tn zRx&&>(nT;2^)MpO0Yvuf9P()-Ksv~ii0E3LO~^^)1X4rpM<$S6i1@QSPawE~sv;pG zkJ#Q_$Wh7gc*t$Y)5s@~MdWd05?TGoUdkCh9a%ui=QN3*cNvLqVsmGZCXyf;*@wIjkw<(+9TEhrZ(>C#1B)QhPoXF zUK++~%1aY96*j`Q7fB*aQZ?00ZK9@4t!eoUbe34%@EWE{xejB}RWDC3l4;v^7}Qah+G=BT}Z3AgiBgQ|d$!nn0&T@;5ko1oCOYqP5F)%4+6 zZR+)yb~;?7A#0*fT?>Q2)?`A1q1@)sMw@caYQ{&Sb@WiK&FN{)A(L*B+V+}Nl(TS? zW@wXnbWH4pS;92hQ5c|UH0zYt3H_9fxJ9c2fsGqoy}51^uMv!>GQXJl{xBDWXGYXP z6Ckmkv5RS*IO#Q-q--&Z*gl)tBt$K@5;sR)( zq7LQ;qz=Z`$`30HYF%~6qBY~I$Gy7Mb(0#s7>DiB8|lHM+ORQR&@sMOFWPySNFv6N zhLNtCxF}t=ameoZtX3TkYJNtK(R(dT9kn(ZbU*B(7IL@XmdXqG^v7}=0piLt;v@X;tjWWUr#x8BEUNrfF<+-NV_nS!C6^Zfjnfnazc@mL*Kh5ymaQ z#cAPqgUOU-k?4ALM)spT*yOmFJ7Xd>m&Z&8?Y3Uc55wi^w9Ysc)jY;63ARYK#%si; zZa2wtHZ2;0R?xH_yM$lo3qnV-u_#7VQ7Sg^nF$=kuK@eox8x zr=nDL_EaJkbc%?%=$*yd&Up2-ncP&6yQ2#s(zuBYp;y9TjX=x!Lt$Ml*r3jFzfc5! zb-L-*nmWkZHWu?N-LJSFxRrGB&|4~0o%RlTdd3S{`iYDv#tEL6%yCT6!Hn$?3{J-$ zSA^W?iezDRrE@!v9eQTsw%K_iw!FllIeNH0x?p3O{G?ttdt&sYl`|s@M)zYI6wR0< z9i1ogC%&PFNj*cDZ0Ut=9pl>Ncd)VGv8>XXsMMDC&^l;jsB(1Pns)wnk)PDHWZkjD z#|{h!8?TJ5n-1~Dfd0D?W2IQ^RxTZ0uv6EXCQfX+`_%lw(H+BfG7o%n^gvLYS(ADP z=D%*%&o~oC<-|xPbr9v*WcRk6x=8Nc9PHjbuJ`IOP4%AL6MExD9qiiuFh%1OO^obh z?ep(l{KVM!j?wXn(TPX(_}JvcBM*&@kBzPS_-Jtk<=U7HZ5`{~RvD{|Q&VI|r#O4X zWhQl{GAy05CayIlY>kdhx)Y$Xl&slce6lH{+g?Lq?~i+t;_G( zrj=&B6+gIkG0(PFUBPR;%f33n8be}2J5wjBiCMNmZ-q$NzhJKYnkZ^IlUbA)S zV?S5wERr^}asNvD+QnGS$t4`8!1?SJ-GaRp-qdZ-E)Kx3W4MTmmz9@uN#(b5vn03Y z{C1AR=p}{;(^jT&K(9p$kJ!vGu-(7XziRQwD9rj-dzaJUH9oM_aBz{ALu9RfdawFn z|EkwtNv~b}{yRHb-0%%?EM_|W3xuB|y_Gs+$UVQ-ZTVew?TaSC7M7XhwTm0N3vPXB@z5xrPP`BrHPozfUsA}hpB z#AF7|R*yVX_+VlZ8he-8G7MwpH;$Suhe&ONDP+buK54y~FL{5=X@2dCPG{P=AzU_p=TofC!$9pTCxY^aYnJw|vq65=k@jYT_ zx0>zM$4v*T@;WK@FIIwTw%mMM|A9XVrtGp_?ybaGOLw|U*j#Q|q8F}Q7(BaV>rvRk zbm}Ho*bnxNFv~6{(Y1?9sm(tW=qlq2A=Ig9X@Wz_pDn%;FitsbgWe_iP-tPXY}-PA z#fC%%DV=M@-KFAdq4;tqZuGAV!ogC4xdrU6N%Q!Ux5mE%tY0_7nElXx;hL_iAoFu8 zX@(LIy6P$JD%fm_x0L2<wdeUxV4|xhl!-RBXd;j6f$#aOPNS@4mL;wcY69LUX1S1?&zxNjO#a1`YXNI1 zE||;}MG_&diknAa;uGz9m)X$q?S? diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/de/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/de/LC_MESSAGES/vitals.mo deleted file mode 100644 index fdc98499322dda3254d461f20f3de137e2eadee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8159 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 Nt7HHlYrP~w{{!LoK0N>c diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/fi_FI/LC_MESSAGES/vitals.mo deleted file mode 100644 index 38454e3df1fc067585e343ab4af5fc7527d3a6b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4004 zcmb7`ON<;x8Gs820k6X&4zJiiDh3A!duAVg;EW$(9eeHdYe(L-iG@g1J5#$;Gd*2R zSM}Hv2_=yNNKr&kB*+1Yhq711i9Nt^xS&Y6AwZyT$bmy71cC#KIPm>FJ-cxdAJUrY zuO5H@_5XkURW+~gy6Z=Z=M?4hlzTp?)H3|vhj{Uv|FBa0)FQ7Pa0%WAZ&d9*{0Qxv z@Gkf?7YE6#2)Y$bYNqZ^KW~?pEVZL(%^n6nkEPV*kr4n_a3;V$@U#n++e z`B&BcFBCg>5_GZuUMTso8;bvRDDxew#up*3sjE=tc>;=^0gC)HQ2c!!ioTcN1MnwR z|8FafAXBSX;b-8Vq1gLRD0=TEX+_^2D0=omnYRvQz6SgPJO@S2LXq=O_RlRSdHWJ% zIm$=cGgbWrlzF~P*;Dl$gc1vR#1=Ux_EY94^3*7GimaDBk5I%Wc_e0yvPP_+*d~wI zB+pkU4^qT-d8R23m9_EuNQ~udlHC3(TD4;TaJwP>(Q#N=2v|Y)qIlpmWj4a zE$f(78{Jb@2b%_;2Q@!1E-|Z#rDk)pZq;cQgF5Yfi0bq(+Mph@X|%a|%;#3`YpVs5 zss(FeK{L1CE^LTF`&_RU>)}z|Osol34_t6jpD?J27UVF+IKRVy9TGw|sxP zg}Rn+yL5f}x{D?W(=G&*?LBqQ#q-7LiD`4HuCI7~)8x5Ht~6x z?fSbX+16Z6)b=Uf*RxKx_tcrPE~>R#(?ehAHD9D{9Xl@QBG|PesjCH__f1p_xwZ1b z!?ZP2=WI%R5_R6St$xbpUJp!yy=pOSB?Wz1v6{G+UTkX9Zi}7jl3k1Hk~eKVd!%1g zD$>4e`#vA4%RY4xf7S@=q~5=MD7EpX&wE?LS?*it_xV;&K!dE^L_rvaXqlqYO+CYS zS+cFZfls1*a-~wfl-X1-xCD=yCU#V_GYqbU!%fdpI-hEn>dd5;9@f<6L`7uBw&)et zx042jH7CJPS1tZCw;k7_XRWEO5upwYHXo3hSKWFis%0`FZ3j(`-n5ugWNkhS^pBHu z`KHO#^4PaAbmgL2A<+z<&bOi)*sbPDIoE#_+I5@DXAM2oT&i8QlK4KYo#6|*E}0N(E2M8o z3`^9|XA@^IGEcoe8+tZzDQ=#CCe-bu0XV0e0Jj8>sH6)!N!xUEIT$ihtD)=lsb*5Jn`*MxLPMun*$gM=j_YytN8`x;SFW3#99V&Rl!65j8IJ(|*e??!Dn?vpq}_$3;8ZsH@8bTbgyu zj7beqA4mU2V&w!-P3IC$DjkO%BFd_=TpWjE&m^L{TO_^muvl!?%4k}Y1>5hNa*c7O z?_v?ko95zntFN{ja_1C;!SQ7>@H$pY93{V`qhF3rTKpX#wI(eI7wMC333H4mHcbok zC1xTu$wQV$7NXM2+Vr#0<~syaj$^V}q{^8j+1vcmT-mHHYzI$qG8?10x!F(C!S)LD-PWnD zySzu3O7q9tZprm*8Run@$8P@LlrnM^rFuaAvDNrse!MI3+jW>mU8weD8IRjrDSsaZ zoYHvEi_XctVf6B7gQ=X%y;|7`2 n6xjS>9eQ1>Bk;> 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 KoMG6*dh;K8?)H!X diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/it/LC_MESSAGES/vitals.mo deleted file mode 100644 index f37507d4bb89eb8c2d3d3fd4cac2ef8f6ad3251f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3030 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 K%Q9umRsR7-_EiZ0 diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/oc/LC_MESSAGES/vitals.mo deleted file mode 100644 index ef097f71c3e1d4538c744db7f6052fd45b96bee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3817 zcmb7_TWlRi8Gxq{E_DlS!!0e)4uQ1L^!S!0O-~Y6jvXgPNqz7omSM{@p#c(>4zs z?d&)A|DS*U`R9-O_dTmfQ{)ekZ-0wYOYqgV@*|yln^Jsgp5Lu-0lo)*rl}|J9n{z1 zKKLZ$Q%^ViDttTjZ$KIM9F(Ph0AGSvoBk^dlKEeTBIg+>gx`mE!)s8+{T99x zz5r$1iw*w-`PAR|-3I>&-wj`Zcfea2d>6bMO8qdD{u5C4^~t9FbC6G^{6^p!6uDo7 zBKJ#B*7-UVIX{HA!=FIW|CbGa-S7n{>-+)oslV`(b^ZY{f%*^p0DJ}Vsr__{ynCSR z=RPQU-rw*jd>8duDDxMgj9-N^{^nVWC$=P3pqW@3n zly!auKL&pTW&Gcp_WweW_bOzHx`jn#{7A#QpvXA@WuAtAg@=dz7)$g%0BKV9LK*)c z6hEAV_re7z`lJmnLy`AX!>={`78Lt^555on42s|U4!$401V0G>-Sppq@eWWw1ZDgb z6u(@CVy{&w_D-Pa`31NiJ_Y&Iv;4$gu0ql8=TP?feAE7WDE{^5ru|<~^!^_dJMClf zkHFiY%x^(ye+0_7DJc4%g<_x8hGEm6Lm9sTMXxJO{hLtq|1Okut~LAxlzl!A#cyAP zw?Ii!AFoPEorE%9&Rpyz=^?V%K$5H>=ksy$Bw136JW7`HlJqE9be1GGYF8ztj>8W( zWzkL217xuS$5N#+{`WU!*_YTrVw3pVgXD+FV&{9v5)X#yJ_-k$ik!FjlGx`E`7l|N zA0Zzlf0Qg|bA)_?{0Z_fiBE7u)!9p%oJ|u7)hWtc5j8=UB>r}+D)F1{W~EotahwIl z+mKQ|FkS1TO{<+vT~;_Xy=J1=bYn}&7N&32>Bu{EI?J3_r#HNHYR0DC7HTFdtUeT~ zIg_e6YkWzyuuqiMd8e~NcgwzeOm|{yoYiZQi@ZK*^q{c4QwIm$=dL|A){p$4?2ZOm zG8V90kcCm&AG;WN6T7jq${a${F&{d!h>ey2MxvViroVyDHif}GuO0k`42MMSeU zC3aXrvChyKYSFTPWZSyrGtQb~4+{;Tv&9;&xft~aUM=AfY3MXQx^7XY%tIzR z+G}TBS~s~`s`pkyH(ON8IGSPVbl{^kyHj1R#MS>546RmjFPg46+4~BfIzX~5G@cdU zvso&Qp}N>u=hH>xadT0>F4p?9>q|E9t@*HZ(H1hTtw%Zwtwk%2pQWu?X3%urINw^v zeO+ugqPG4N&g3yWq@@rL{9G^JenwV@& zKB_0i+mpu*k57z`kF2(8x36^XWH#hdA3>4TR$XbG=CbFwOIweQ?zS#jQv?HXqtFWo05PUXMLi_LJ`{36xzhSD&z(R*%i1l|&iB>;1CXST093BVV{g<=zO&1O*}4UH!J^s+QS zYZDVpz0M>YzkKD|V;Y}vC0E^VzCKdE>2N$_a*@?H5|N|O)G;|qC?c{7$pP};d{8c` zn9OzbMb;Hv%@gJJbzQR2oq&8k>SBc|B5(hg%^Ed~$%GLJ96U&|apG^hY})9}?X4oK z? zdlGxv4Q`ga!RW#g;r347jpKWo(b6V~>6^`ncZ(pkr!Uhka(;U&xj_#@BpAl`8#+)> z!k8?wi0s*{TSTI_)7+Io#IErzlMs%=2TTxbZ#gwb_zJ3!FV2MbO32^d8pizE?oKTu z(1|Db!UVo@?LEPNk9Fn24LOt8_VE!n=4>B5ZfH}4>=L)##Nq4rfa^0$I3BPW+vi-F zU)_M}bdgt&76nEB;bmH4OG#HP4J|Z${B}&n tslALCc`n3?o#7*)6BFq^mmoB11s_FuU%weLY`8(ZvcS-<+4fGW`ajgu!dCzQ diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pl/LC_MESSAGES/vitals.mo deleted file mode 100644 index b42daa4e2618f669eef729de7b2ab90336cd30d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3501 zcmb7_U2I%O700L0P*|WJp#%tDQov)PY8sYzMwvVc&RK!+^G84aE=Y3U2kAWO(0NBd z+J8St@;Uek@DxaTKjFCm;>VUy(Y|#MS7k4Np8-PzXPEf`-2~U3w#*;cl`W6K>XPIsFvVMQi9}PgOa50H^EPXZIJZ-4l26O z%OJ`BAxP)l0ZZVILHyXyeE%2VB;@|ukN+KuX#GDy(*GU^qw|k~$H3zt`LF87p9N{% zDoB0_Jsn8)x&=N8z5;$8e8bQG9^~l%1tdHE2mBIv440yF&Vl5|t03v~Ef7ms10=aA zNdEh_AAbcTJ+}S)PeJ_H4l26uuYCWvAnpGXNc#NE_y6VRkHATEkE0;jbqqWTp7(qf zBzZ4*wm@2+f@G&Hko0;PB)`4}()!myavw*b^XdB{3Y}4=j{nHE^wHkWqMSt`xf3XK zKZs!`QOH&#m%c9#Q0Q?S?XUU%*Fn;K_>mpY`OY}_6_hh5WM_KIlrJc@PNRGX1twt? zlu4A)uj)Hr^(6n&_ZZ446pB0YDcON+OyAT1MNR&F-1o_+V<;5!C;S-YuHi>9`v`UB z>n3w-K8{TwoD9)QTB0tU>Pc>;wkEY~ep9Ge)MJU3Ohr?&OUhYxDR;vXxzJ!w34y8%SD?+bJgIv$#}zLI^?dUEYGZLWO0QpnzSPvTTG>- z3OCe2&YqGQmWkQZDwMn@Q^Pk!41L)Z9mE;NlB^!9fM2O`5r(8EyDA%wT{R-))pH%+ z@I-$}c1)VHC8L$YeHt+9u-!R4rKRhdG}@m|QWHSFN%u!AB#_sJ0&H%b#1URL+6j~= zm+g;jn%L2nYhHLwxE8Cma;pN|vS#2vWi(fsCqhe%z>zYADRAZ5Kmop{I&#>7HnpJz z*othx0xi(WbQ3|hqM9woR^f3ST8`-JN~w94gm8_;_#g~dyCPw$h3?$z&ejfe=NU}J z)(}zxLgoXfHsyYI%^--_pkAkS>xm=v)-By~9WmL04l?D4p#afoG!2IAy0-)F)RuuO zUkS_CWlHnYyi{8*uSkkzqsy0}Du%8K>&k10NE-`SeVRXGAbUl%1fOZ6S$(`({YJBc z_e9Y*hxNLdL51>~6rE!Kpg+x%xU_U->B)oRs+FnIg27|cI3Z7Pnv*x&WD*OdFYurx zQY+o;`r2ao{J}cX1db^`sRyrVnxC&LSE|JsqP0x1Y^S+SimshKa{e&fwsbb6Ni3_FY%7aHyn4xB5 zh$nxhGF7RT*fLK|&*GW%q*fVXq?d<1C1bolw%*^myVKw0B5qI~%7dO(l3g~|?QJKR z@4uSLP%ASoCK#@gv$|-bz9xA8PHMs^V=G}#_HR)#+JLR{!Vw7B(9{KAP~57$?TdWF zCZG58(zlFE8_Y$x7xAwNf{32ftyGUgHUvlk5v}NSb;U84yf9227 z#QB(#l~UKMhm)LuW zEjRD((8PL_=50#D4 l3y3^-b4ak9HhOT&XM-;=8^x{^E{Sa*=Ec2K<(Y`?;-?b zkpd47bPg{-O00cFq9SM7Lj(K$f1pc{5m>)kYe|?M|NqE;6~7mtrm*#{;TNpcO${sqUurX z3s@43wjh@mxt89GPquCHi?CcoF7N8X{yyRE=UXy8jJ_Q9@4&_VUG{t`@$kB)i@XhA zB&jHzF`O6Vjqxu2`y>4IiJ&!sBeJ$ukz%!2MZBALl+XwNOvB6W2Miw4@c$%d^Mz)4 z(Bj>_+b$x{Z1@I8gx?;#?*4a&t$itjiy0pik diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt/LC_MESSAGES/vitals.mo deleted file mode 100644 index ebf4c1123afc32a7faca20e4fe9504cb69f9fcf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3935 zcmb7`ON<;x8Gs82fh++MCp=;vDH{?JoSB_jKVpx)4r{O1-pG&9K8%sTQf+tbPAxNC zLs#`U>jMTU3Ic_P5FrPoAmoDq$pQ(%!3Pcu7cP-FkpnLY2@Xi{1%wnp@clhKJ8~Q& z(VFV7US0M7fBp6U^ZOlly`XrGQa(tz_svQz!+*Vn7tg7;D#cGN^126}gAc$@RqY;p z8|_Q*E_em4H=xXW5z5lvg};SYtMM-|NxuIQlzpCuGXLA~KKK%R2>uAl zykEh$!^}!(-V!evzX)YN3q`I?C~|B;(fruG$x&*kiL|gtG4E zp@z>vk^dSLd;GW>{}~kde-8PnUswDilzBIytn+s$^ZpIxUfqXNzaKsbW#1ZI~p!my2DPk{qo}kE{@`&vuPCQ1Lp~zFC)F~g92G1di*hC(& zS*xsJBlw}JE;`HeG0H9q$5}qpydSOVqL;`lu}RM6XkDUVaekJwJmPi!QQ*suzPYL+@zL^Ub$h`${uYrN*x zd=b@Lx9bxVZAz`*F>5xu%T@=Q1)m2sH!!Yi*1DFO&CP~Y$6O5RnD-&7V_VS%b=+pr z=IXf5t$rj`3no(w*2IElZa-Jp5QFx)UMn`jQ@Y)?CRjai!9{(<=uU3eXLomE?1$F$ z^oEO_Vy&L|-gLrpiBDa&F@4@e(+$%u1Qy$U^rVZYinSxt=4f4?_4<;@bCbobC$xR0 zpW6^@D%-hUzw2yTzkQR*%H>9>&(OZ!@AP*coiFRMw07%y%NKgx7g?%f#|2#kyIyqb zYQg6{6V*a)t-R1MOSaTWn_-`>I^|NUFWcPff$1WzTFjDeL0`XE>$*fQwzWx9kyD+v z>rtKdCe_XTy{b}?_8Hsr`Ib84GZ)ck9kY(>y<3Me8!!3%v)jY{+$XH>^X;C%3UYSi z1;SQ{mMyBasrM0Hj%>Sc;JZ;iIa@7$u5UBF;JRqkHnF4Hovq*!6mENt()mogO!rM@ z>ETRmj#XstNEW@~dUo7Eu=dy(YRRHMd)rYhdd`~aIu`1{VDka4x#TuFQ7z*USsFAx zddVVA(NFm>&_8n4iQB&^4T1OFvz7oyok$m6m;R+34e@ zXYviNk8F-cLh=btKKiW3l@-@M$|BiDfhM&TYkDo+_IWHea7wF>=*ehH_v6%=#WN=+ z!Zz!TspFn|ogu_lA1R}KCQkRe#$|_f(lL3kadvfOp>}XGPlV;*YbUbN#ck<>Yc8Vk z%IzvQ57wG9wV6Y@*=Wri*wbjD@`c*y5|!$njN7{FeGSC9P-}aex>!3#0O{j`EnTlq zwYvqkt|oUfv~<=ln_+h5upU)sAItQvS>1em^8Kb@>jN(Dnc)voXGT$ePGYD?KD;)(>Z@=+ z=XHWxf?R+jv#ZT>Pa-%k8Nh1X z_y0)(uZ#XR>l8hsH;iNeXSP#-kqspS46i37kGft!1*41J?YsStY*1zfH}GXX;LZ>M zgTZP!Cnez^_2XpV)oC{%c$Vp4_(OCz>SUP?&LstLG#57`p#_~4U0>w{%;dGrQq~$? z^SVF0Aqk?q;EQc_B9K^ePU|?A+(?FS*|)rcVlUdD-V+30WC*X!UUxx8MQNshUFBn#qROCrF6!+RYb zqWLG1M{Gry!?Cnr>c5&#?sfnG diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/pt_BR/LC_MESSAGES/vitals.mo deleted file mode 100644 index ddcca6d47d22958791c588c99c9626db544e5a19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7407 zcmai&ZH!#kS;tRlfM(mKrIZ#5G>5e5+99*Mw&NyV$1l5Uuj9mPPrPe8Eg|jMxo2js zedpfkeHnX=1S+DX5-sWnP+LH1s!Aj&iYTfoP%5Zk5fBt1-ceB1hA)r`2_Yd-K171w z|K2mRvv}QJ`RwnWbI;3jp7T70u|pgj3{V}1qx)(`N9=P%x1%p2j0 za0dPZ{C@Zfyc7N_{9*W?p?(LAKS=#9_)ho^cn6$=8h0r02%M#U0`7x7$Q0(&P)mOf zYM!S<{aGmaeiyz4z69@v-+=FeufZRO??lL-gooe)d>q~je-Y~Yvrzs26z+%L3g7Q! zlbUxPz8Ri?Z-Q$Om6#90Z@{OZtrA-%V{T#jxZiV(w!n>${7HS{Qz#oFYAL=iL z?=M50*Q=rZHK=vo#NfBXw?kB7_Cv|_K&T&qlIs*~!8NG)e-28nPeHa~J_n_b-wymT z)I2YQ`q!b>dl72Bzk#xge}=M`SHk!If$yWP&D;ZKq0aA7sQJ23dbkGZYI1l5el*ly zhHTBe3N`U{3vkLJG{N)Jb&`nRF_UxJeRNq7)OQ2YN(;B!!V z`x=x!{tW)Y_ZjoIQ2Mxt(zV|wq1N?K^Id~luYel&38?jc4Za)xCam=bnaX?}YW!cr z`{6&r1Mu}sqV*3$jXw!B|Cvy~0Oc>2q4YI^_ri}s3x5a7zg~jxf!~G?!Z%~Y?}ewK z`d@{b=hJWjei_cfe}R(k&UZBS_pZSEpyXME_r1=TB`CQP4qN*uq4s?<)IScj-Y4Nt z!QX@YGk?b)`SriUIe6!fA`^TFO0Pc;WtYDUHQ!gE^zp}mFG2PDr@&VrBAahR$^E}j z{`6LyRQh=j)c1o>>puc@-X9L_d8mH^>U@3!O1{rSjsHWaeZB-G&) zD$jjd*6$lG?|EJ~vx>h-l673^Bi@F6x9Q9HrniMpi!3k9(#XY$+e|!fK6gEDmR(u; ze9IO|R@ySNgDj29EH}$>S(xQ4D@wDxRr zzIVTZ>9z8T8@f(hGJ=ix+^l4|xA#V7Wvi30-YK8BEsOluy-&ji>@Z7`IPIBJaWT~A zApNA?MaVoWT^VPo9eRX{)2j57?~RN$P7!!e_nLf4St-k}?fGq(XB}Ul!M(p$n@QZU zXWQ0AQBFUbb?L~SnA3K$H1!<`G+8Q~27Rm>A5zC9Xf#3(vZb#-j>}L`6BM6`^~uCt&(J?mS)%Y zn^l*ZRo^U``;Sz+N8!nPCdu$xg_#HD@M*?#W3$L{Hu<*-N8-ra$d%4^^K3BoHD++7b(}(+j$9H)O}`j>D0K2=Hnf{AZ(48q zJmaVmc5BY2oup#M;r}-)^O*O;$@Du@G|OJC218WGiju$S8`iKm6ppdEWwSKF)%)3X z^=!;=yzDvOEzP;OC}j_03nd_I5qg2|injkAwwi=oGc znxJ4V3<)@^v4T+Bm3`Cpd57&NX0`iUMU1POc7`=8$Z!m8X~gcEP0--%{dQKJeXh4W z?)A&r{kwWM`fK9^o(N7@G3_S0*o}C=3gb{?+T-qM1z(W7zvT5ny9z7GqZkBIaa zwTxNEdD5tugv@G)O)~v@i2dvRtV*J=)hNUO#NQ;+*WRiyf5Oo1I(Fjmtul8uit$kE zy6nhCz7r4F{CX3?F@>@(rHwBQMdtPEZfMr)@DyOf`Irr?r{Z=&RZ>yh%U$GWwe)P) z5f#$DkI@#6Q!kF#QZU9RvBv`I?asoOQ|WK_qtvChnucr~`?;`Ew*ydq3+AJ#4F1YIUL=SO(kl|1Ictq;F>E$h8u zD_6N%T4$ryWuHr^McYJ9JJY_iv$S;zJ6N;_7Y-b0Ej-v-IAj-&EFR|l(89vZ zIaide4Z>-WIF5DEF6UL6*`>6sQeO~Co0qvLNlx|#WDkm<#~GIPD)iXe@NS?%?q;0C z1etc0msO8A=Iz71G#mKVu>82-}`{qSXZIdUt2A z>9AFMXztKK)_J1U&U_S?t!1t$ne?Kao11AT6|udg$X_hlbXZr5V+W7g=JnXV)E>77 z_U{Z|_b%`B6){>1iy^AcT`l(PaA0v9VsF>uAc`SI6u0|+2%)kv?qX(&L$~esz#@S+ zt!d52VHl$rHxGbg!J4jMVw zZ8A`ohy4hUCNB zts@pT+3a{+lOG@ydsWs-A074fb0zjT?sSWEyH$HTF$*FEhGsSbHDKYf3(2kOuE$T6{T#Ut$eiKF5cwe|Mgqvp zUpirzhFMGk%}Qv5o;|7h(GoHIi}qp#O1#o@aWC;+&k*g%rI}+GG^D zxRUh7aEm$~)#8nn(cBR2si-;?M9qe~K@8)M_K>g&`2@Fxa=e?|X-)EuwQ?WUGLWbD z_~FLsH+Km?r|Yhb4~HzCD7Um*JtO_+4wkOyNZiJZntZ_o!uI@aBHakJ$Ow#=m+;&eD=jT|5RlJa~78Wg|clOnDP z^8Cuqu1@Fq61UDf>U)qxx7h{9JeA>VOOuqIRA=NkiIDIs3y!JQ$uKE?eNF4yz!mA4 zk)o?$;R$Yp{tKo2OrU&zcherhr5;GeOQ39$e#F#l9NDVF96O2&SVfbKD0xSj>Glic z{wS3MpiXKOG@7I)(hdjXq()Jqh*RVz{?^;5)Bjp&46c6=T!~w&u{mF-N}6$<{)uf` WH(aN=7K;u)4zM&SL1*AY!~X%hfcP)~ diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/ru/LC_MESSAGES/vitals.mo deleted file mode 100644 index 1f58435ca13ab609516a096a9b92757bb1a9b727..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10711 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 diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/sk/LC_MESSAGES/vitals.mo deleted file mode 100644 index 73a62eae8f3dbdcc96950026767b827b4a5a8a4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8559 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 TGni3jxETbMfw@Gg3?TmvS6+-W diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/tr/LC_MESSAGES/vitals.mo deleted file mode 100644 index eee9eddecf6a2b8a7643ca5f9799b8c7bc807079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8416 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 PQGvu4Rqek@%T513?2sGM diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/uk/LC_MESSAGES/vitals.mo deleted file mode 100644 index c24b01bae2958aa89d815b602c200fbd2c0f01bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10967 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 l#_5~PO { - 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', 'processor' ]; - 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 = 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'); - 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(); - }); - } - } -}); - - -export default class VitalsPrefs extends ExtensionPreferences { - fillPreferencesWindow(window) { - window._settings = this.getSettings(); - - let settings = new Settings(this); - let widget = settings.widget; - - const page = new Adw.PreferencesPage(); - const group = new Adw.PreferencesGroup({}); - group.add(widget); - page.add(group); - window.add(page); - window.set_default_size(widget.width, widget.height); - widget.show(); - } -} diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui deleted file mode 100644 index 76d1473..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui +++ /dev/null @@ -1,1211 +0,0 @@ - - - - - 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 - - - - - - - - - 100 - 0 - - - 0 - 6 - 6 - - - 1 - 0 - start - 5 - Menu always centered - - - - - 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 - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor system - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor network - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor storage - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor battery - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - - - - - - - - - - - - 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 - macsmc-battery - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 0 - 12 - 12 - 6 - 6 - vertical - - - 0 - - - 0 - none - - - 100 - 1 - 0 - - - 0 - 6 - 6 - 6 - 6 - 12 - - - 1 - 0 - start - Include static info - - - - - end - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled deleted file mode 100644 index 7f4d0c0245fb00f704dd9dffffc261d44f72d7a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1780 zcmZ8hPiP%Q9G+@pYtxuCtu<8xDWbfm?0XHB*djtff*w2sG@@RXdGAfKqq{rn&TR4$ ztMpKzik`d_G{l<)seevN1<57YV-8ZhiFheOQw62uRKIU#pJ`qA_`dh;yqVwpX7+pG zRat78J5fIq;Mam~+*5mdz}H&8&5-%-xOh>V1%Gp|5JL|NaU0K#`(TKd#Gl~50aGrv z7ITxSmQ7Tewp8D#+-j5C){=HIwHz))V=}PdTEt#p2-sI+KlpxN7#OKB3MR&C90HHu zfy2-b0o=;~$Dkhu9swQ&wqJhi75rd~{r)E7Dz#jvR zeepJZ>izI9g4clGb9I?M^%3~rgExqG-y7z6P!GYs3f=~;U-|Acj;H4QZ1NEBZ1;%< zedia{@dM<+3fWdvD=6(8{?{S}Qu1{a%Jk%UN0iFVWUSHetb=Lj~@C#-~JsSjZM8SpId)$_O8^r?9+bKrU4)`veHrB8hrege*bk)6>deQNsWz!!ko>ZfJ; z)V_Z38t{?%;0^lJoc|K|GVspK&T0D8?DGbA6X;EMR_If6{1*5Z;MZ#Q2l~{k|2p^v zU=y<(b)<8uT)}HRjZQN$F0%N%OljjxWu{z-D=QaOEMmK2oyy|W$X-01!H9F^mQDFq zRQBUc_TyNLPMs7DX`6oPFkXl~oVUvLf5G6F(#_1kGiB7xdVY2PjYr{MQT-A%*=DFC z%9ONKsWMeZ3^PPDbXcq|g_d8>SFj-S!S6w-wos}UEtoQs|F5T2NS9!I8-dgI#k76k zw08ri9RjC~=7lYyel&-x*6S9=YKLr!bRHElS82#1)>&B>;!4D8SEzxromi`M^6A9_A-A4_5}?Bkxey6LXW9$b4i@BHnx^9t79dDzd2w zZRRrG-;U>DLBHcxr`~AwaNMuJjy{h~^b>2-YjId5R-9=XyOz2BJ*&UbS yuKTcLQdghMZok4sx@+E|>ZF{v7~IpMC!LC%&J_E>bMqChs?rP^%5&j6JpTd@+h;TY diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml deleted file mode 100644 index 71e4935..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - ['_memory_usage_', '_system_load_1m_', '__network-rx_max__'] - Sensors to show in panel - List of sensors to be shown in the panel - - - 5 - Seconds between updates - Delay between sensor polling - - - 2 - Position in panel - Position in Panel ('left', 'center', 'right') - - - false - Use higher precision - Show one extra digit after decimal - - - true - Alphabetize sensors - Display sensors in alphabetical order - - - false - Hide zero values - Hide data from sensors that are invalid - - - true - Monitor temperature - Display temperature of various components - - - 0 - Temperature unit - The unit ('centigrade' or 'fahrenheit') the extension should display the temperature in - - - true - Monitor voltage - Display voltage of various components - - - true - Monitor fan - Display fan rotation per minute - - - true - Monitor memory - Display memory information - - - true - Monitor processor - Display processor information - - - true - Monitor system - Display system information - - - true - Monitor storage - Display storage information - - - true - Monitor network - Display network information - - - true - Include public IP address - Display public IP address of internet connection - - - 0 - Network speed format - Should speed display in bits or bytes? - - - "/" - Storage path - Storage path for monitoring - - - false - Monitor battery - Monitor battery health - - - 1 - Memory measurement - Can use gigabyte or gibibyte for memory - - - 1 - Storage measurement - Can use gigabyte or gibibyte for storage - - - 0 - Battery slot to monitor - Which numerical battery slot should vitals monitor - - - true - Use fixed widths in top bar - Keep sensors in top bar from jumping around - - - false - Hide icons in top bar - Keep top bar clean by only showing sensor values - - - false - Make the menu centered - Center the menu to the icon regardless of the position in the panel - - - "gnome-system-monitor" - System Monitor command - The command run when system monitor button is clicked - - - false - Include processor static information - Display processor static information that doesn't change - - - diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js deleted file mode 100644 index 39d175a..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js +++ /dev/null @@ -1,671 +0,0 @@ -/* - 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. -*/ - -import GObject from 'gi://GObject'; -import * as FileModule from './helpers/file.js'; -import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; -import NM from 'gi://NM'; - -let GTop, hasGTop = true; -try { - ({default: GTop} = await import('gi://GTop')); -} catch (err) { - log(err); - hasGTop = false; -}; - -export const 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 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 values = '', total = 0, avail = 0, swapTotal = 0, swapFree = 0, cached = 0, memFree = 0; - - if (values = lines.match(/MemTotal:(\s+)(\d+) kB/)) total = values[2]; - if (values = lines.match(/MemAvailable:(\s+)(\d+) kB/)) avail = values[2]; - if (values = lines.match(/SwapTotal:(\s+)(\d+) kB/)) swapTotal = values[2]; - if (values = lines.match(/SwapFree:(\s+)(\d+) kB/)) swapFree = values[2]; - if (values = lines.match(/Cached:(\s+)(\d+) kB/)) cached = values[2]; - if (values = lines.match(/MemFree:(\s+)(\d+) kB/)) memFree = 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, 'Cached', cached, 'memory', 'memory'); - this._returnValue(callback, 'Free', memFree, '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 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 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', 'uptime'); - - let cores = Object.keys(this._last_processor['core']).length - 1; - if (cores > 0) - this._returnValue(callback, 'Process Time', upArray[0] - upArray[1] / cores, 'processor', 'uptime'); - }).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 => { - // wireless has two headers - first is stripped in helper function - lines.shift(); - - // if multiple wireless device, we use the last one - for (let line of 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 values = '', target = 0, maximum = 0, current = 0; - - if (values = lines.match(/c(\s+)(\d+)(\s+)(\d+)/)) target = values[4]; - if (values = lines.match(/c_max(\s+)(\d+)(\s+)(\d+)/)) maximum = values[4]; - if (values = lines.match(/size(\s+)(\d+)(\s+)(\d+)/)) 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 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 battery_key = 'BAT'; // BAT0, BAT1 and BAT2 - if (battery_slot == 3) { - battery_key = 'CMB'; // CMB0 - battery_slot = 0; - } else if (battery_slot == 4) { - battery_key = 'macsmc-battery'; // supports Asahi linux - battery_slot = ''; - } - - // uevent has all necessary fields, no need to read individual files - let battery_path = '/sys/class/power_supply/' + battery_key + battery_slot + '/uevent'; - new FileModule.File(battery_path).read("\n").then(lines => { - let output = {}; - for (let line of lines) { - let split = line.split('='); - output[split[0].replace('POWER_SUPPLY_', '')] = split[1]; - } - - if ('STATUS' in output) { - this._returnValue(callback, 'State', output['STATUS'], 'battery', ''); - } - - if ('CYCLE_COUNT' in output) { - this._returnValue(callback, 'Cycles', output['CYCLE_COUNT'], 'battery', ''); - } - - if ('VOLTAGE_NOW' in output) { - this._returnValue(callback, 'Voltage', output['VOLTAGE_NOW'] / 1000, 'battery', 'in'); - } - - if ('CAPACITY_LEVEL' in output) { - this._returnValue(callback, 'Level', output['CAPACITY_LEVEL'], 'battery', ''); - } - - if ('CAPACITY' in output) { - this._returnValue(callback, 'Percentage', output['CAPACITY'] / 100, 'battery', 'percent'); - } - - if ('VOLTAGE_NOW' in output && 'CURRENT_NOW' in output && (!('POWER_NOW' in output))) { - output['POWER_NOW'] = (output['VOLTAGE_NOW'] * output['CURRENT_NOW']) / 1000000; - } - - if ('POWER_NOW' in output) { - this._returnValue(callback, 'Rate', output['POWER_NOW'], 'battery', 'watt'); - this._returnValue(callback, 'battery', output['POWER_NOW'], 'battery-group', 'watt'); - } - - if ('CHARGE_FULL' in output && 'VOLTAGE_MIN_DESIGN' in output && (!('ENERGY_FULL' in output))) { - output['ENERGY_FULL'] = (output['CHARGE_FULL'] * output['VOLTAGE_MIN_DESIGN']) / 1000000; - } - - if ('ENERGY_FULL' in output) { - this._returnValue(callback, 'Energy (full)', output['ENERGY_FULL'], 'battery', 'watt-hour'); - } - - if ('CHARGE_FULL_DESIGN' in output && 'VOLTAGE_MIN_DESIGN' in output && (!('ENERGY_FULL_DESIGN' in output))) { - output['ENERGY_FULL_DESIGN'] = (output['CHARGE_FULL_DESIGN'] * output['VOLTAGE_MIN_DESIGN']) / 1000000; - } - - if ('ENERGY_FULL_DESIGN' in output) { - this._returnValue(callback, 'Energy (design)', output['ENERGY_FULL_DESIGN'], 'battery', 'watt-hour'); - - if ('ENERGY_FULL' in output) { - this._returnValue(callback, 'Capacity', (output['ENERGY_FULL'] / output['ENERGY_FULL_DESIGN']), 'battery', 'percent'); - } - } - - if ('VOLTAGE_MIN_DESIGN' in output && 'CHARGE_NOW' in output && (!('ENERGY_NOW' in output))) { - output['ENERGY_NOW'] = (output['VOLTAGE_MIN_DESIGN'] * output['CHARGE_NOW']) / 1000000; - } - - if ('ENERGY_NOW' in output) { - this._returnValue(callback, 'Energy (now)', output['ENERGY_NOW'], 'battery', 'watt-hour'); - } - - if ('ENERGY_FULL' in output && 'ENERGY_NOW' in output && 'POWER_NOW' in output && output['POWER_NOW'] > 0 && 'STATUS' in output && (output['STATUS'] == 'Charging' || output['STATUS'] == 'Discharging')) { - - let timeLeft = 0; - - // two different formulas depending on if we are charging or discharging - if (output['STATUS'] == 'Charging') { - timeLeft = ((output['ENERGY_FULL'] - output['ENERGY_NOW']) / output['POWER_NOW']); - } else { - timeLeft = (output['ENERGY_NOW'] / output['POWER_NOW']); - } - - // don't process Infinity values - if (timeLeft !== Infinity) { - if (this._battery_charge_status != output['STATUS']) { - // clears history due to state change - this._battery_time_left_history = []; - - // clear time left history when laptop goes in and out of charging - this._battery_charge_status = output['STATUS']; - } - - // add latest time left estimate to our history - this._battery_time_left_history.push(parseInt(timeLeft * 3600)); - - // keep track of last 15 time left estimates by erasing the first - if (this._battery_time_left_history.length > 10) - this._battery_time_left_history.shift(); - - // sum up and create average of our time left history - let sum = this._battery_time_left_history.reduce((a, b) => a + b); - let avg = sum / this._battery_time_left_history.length; - - // use time left history to update screen - this._returnValue(callback, 'Time left', parseInt(avg), 'battery', 'runtime'); - } - } else { - this._returnValue(callback, 'Time left', output['STATUS'], 'battery', ''); - } - }).catch(err => { }); - } - - _returnValue(callback, label, value, type, format) { - // don't return if value is not a number - will revisit later - //if (isNaN(value)) return; - 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 => { }); - - // is static CPU information enabled? - if (this._settings.get_boolean('include-static-info')) { - // 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 lines) { - let value = ''; - - // grab cpu vendor - if (value = line.match(/^vendor_id(\s+): (\w+.*)/)) vendor_id = value[2]; - - // grab bogomips - if (value = line.match(/^bogomips(\s+): (\d*\.?\d*)$/)) bogomips = value[2]; - - // grab processor count - if (value = line.match(/^physical id(\s+): (\d+)$/)) sockets[value[2]] = 1; - - // grab cache - if (value = line.match(/^cache size(\s+): (\d+) KB$/)) 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 => { }); - - // grab static CPU information - new FileModule.File('/proc/version').read(' ').then(kernelArray => { - this._returnValue(callback, 'Kernel', kernelArray[2], 'system', 'string'); - }).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; - this._battery_time_left_history = []; - this._battery_charge_status = ''; - } -}); diff --git a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css deleted file mode 100644 index adec425..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css +++ /dev/null @@ -1,16 +0,0 @@ -.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/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js b/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js deleted file mode 100644 index 77c47f1..0000000 --- a/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js +++ /dev/null @@ -1,337 +0,0 @@ -/* - 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. -*/ - -import GObject from 'gi://GObject'; - -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]; -}; - -export const 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 'runtime': - case 'uptime': - let scale = [24, 60, 60]; - let units = ['d ', 'h ', 'm ']; - - // show seconds on higher precision or if value under a minute - if (sensorClass != 'runtime' && (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 / 1000000; - ending = 'W'; - break; - case 'watt-hour': - format = (use_higher_precision)?'%.2f %s':'%.1f %s'; - value = value / 1000000; - 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 changes 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/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js deleted file mode 100644 index bbcaac6..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js +++ /dev/null @@ -1,1571 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import St from 'gi://St'; - -import * as Params from 'resource:///org/gnome/shell/misc/params.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as IconCache from './iconCache.js'; -import * as Util from './util.js'; -import * as Interfaces from './interfaces.js'; -import * as PixmapsUtils from './pixmapsUtils.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as SettingsManager from './settingsManager.js'; -import {DBusProxy} from './dbusProxy.js'; - -Gio._promisify(Gio.File.prototype, 'read_async'); -Gio._promisify(GdkPixbuf.Pixbuf, 'get_file_info_async'); -Gio._promisify(GdkPixbuf.Pixbuf, 'new_from_stream_at_scale_async', - 'new_from_stream_finish'); -Gio._promisify(St.IconInfo.prototype, 'load_symbolic_async'); - -const MAX_UPDATE_FREQUENCY = 30; // In ms -const FALLBACK_ICON_NAME = 'image-loading-symbolic'; -const PIXMAPS_FORMAT = imports.gi.Cogl.PixelFormat.ARGB_8888; - -export const SNICategory = Object.freeze({ - APPLICATION: 'ApplicationStatus', - COMMUNICATIONS: 'Communications', - SYSTEM: 'SystemServices', - HARDWARE: 'Hardware', -}); - -export const SNIStatus = Object.freeze({ - PASSIVE: 'Passive', - ACTIVE: 'Active', - NEEDS_ATTENTION: 'NeedsAttention', -}); - -const SNIconType = Object.freeze({ - NORMAL: 0, - ATTENTION: 1, - OVERLAY: 2, - - toPropertyName: (iconType, params = {isPixbuf: false}) => { - let propertyName = 'Icon'; - - if (iconType === SNIconType.OVERLAY) - propertyName = 'OverlayIcon'; - else if (iconType === SNIconType.ATTENTION) - propertyName = 'AttentionIcon'; - - return `${propertyName}${params.isPixbuf ? 'Pixmap' : 'Name'}`; - }, -}); - -export const AppIndicatorProxy = GObject.registerClass( -class AppIndicatorProxy extends DBusProxy { - static get interfaceInfo() { - if (!this._interfaceInfo) { - this._interfaceInfo = Gio.DBusInterfaceInfo.new_for_xml( - Interfaces.StatusNotifierItem); - } - return this._interfaceInfo; - } - - static get OPTIONAL_PROPERTIES() { - return [ - 'XAyatanaLabel', - 'XAyatanaLabelGuide', - 'XAyatanaOrderingIndex', - 'IconAccessibleDesc', - 'AttentionAccessibleDesc', - ]; - } - - static get TUPLE_TYPE() { - if (!this._tupleType) - this._tupleType = new GLib.VariantType('()'); - - return this._tupleType; - } - - static destroy() { - delete this._interfaceInfo; - delete this._tupleType; - } - - _init(busName, objectPath) { - const {interfaceInfo} = AppIndicatorProxy; - - super._init(busName, objectPath, interfaceInfo, - Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES); - - this.set_cached_property('Status', - new GLib.Variant('s', SNIStatus.PASSIVE)); - - - this._accumulatedProperties = new Set(); - this._cancellables = new Map(); - this._changedProperties = Object.create(null); - } - - async initAsync(cancellable) { - await super.initAsync(cancellable); - - this._setupProxyPropertyList(); - } - - destroy() { - const cachedProperties = this.get_cached_property_names(); - if (cachedProperties) { - cachedProperties.forEach(propertyName => - this.set_cached_property(propertyName, null)); - } - - super.destroy(); - } - - _onNameOwnerChanged() { - this._resetNeededProperties(); - - if (!this.gNameOwner) - this._cancelRefreshProperties(); - else - this._setupProxyPropertyList(); - } - - _setupProxyPropertyList() { - this._propertiesList = - (this.get_cached_property_names() || []).filter(p => - this.gInterfaceInfo.properties.some(pInfo => pInfo.name === p)); - - if (this._propertiesList.length) { - AppIndicatorProxy.OPTIONAL_PROPERTIES.forEach( - p => this._addExtraProperty(p)); - } - } - - _addExtraProperty(name) { - if (this._propertiesList.includes(name)) - return; - - if (!(name in this)) { - Object.defineProperty(this, name, { - configurable: false, - enumerable: true, - get: () => { - const v = this.get_cached_property(name); - return v ? v.deep_unpack() : null; - }, - }); - } - - this._propertiesList.push(name); - } - - _signalToPropertyName(signal) { - if (signal.startsWith('New')) - return signal.substr(3); - else if (signal.startsWith('XAyatanaNew')) - return `XAyatana${signal.substr(11)}`; - - return null; - } - - // The Author of the spec didn't like the PropertiesChanged signal, so he invented his own - async _refreshOwnProperties(prop) { - await Promise.all( - [prop, `${prop}Name`, `${prop}Pixmap`, `${prop}AccessibleDesc`].filter(p => - this._propertiesList.includes(p)).map(async p => { - try { - await this.refreshProperty(p, { - skipEqualityCheck: p.endsWith('Pixmap'), - }); - } catch (e) { - if (!AppIndicatorProxy.OPTIONAL_PROPERTIES.includes(p) || - !e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_PROPERTY)) - logError(e); - } - })); - } - - _onSignal(...args) { - this._onSignalAsync(...args).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - async _onSignalAsync(_sender, signal, params) { - const property = this._signalToPropertyName(signal); - if (!property) - return; - - if (this.status === SNIStatus.PASSIVE && - ![...AppIndicator.NEEDED_PROPERTIES, 'Status'].includes(property)) { - this._accumulatedProperties.add(property); - return; - } - - if (!params.get_type().equal(AppIndicatorProxy.TUPLE_TYPE)) { - // If the property includes arguments, we can just queue the signal emission - const [value] = params.unpack(); - try { - await this._queuePropertyUpdate(property, value); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } - - if (!this._accumulatedProperties.size) - return; - } else { - this._accumulatedProperties.add(property); - } - - if (this._signalsAccumulator) - return; - - this._signalsAccumulator = new PromiseUtils.TimeoutPromise( - MAX_UPDATE_FREQUENCY, GLib.PRIORITY_DEFAULT_IDLE, this._cancellable); - try { - await this._signalsAccumulator; - const refreshPropertiesPromises = - [...this._accumulatedProperties].map(p => - this._refreshOwnProperties(p)); - this._accumulatedProperties.clear(); - await Promise.all(refreshPropertiesPromises); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - delete this._signalsAccumulator; - } - } - - _resetNeededProperties() { - AppIndicator.NEEDED_PROPERTIES.forEach(p => - this.set_cached_property(p, null)); - } - - async refreshAllProperties() { - const cancellableName = 'org.freedesktop.DBus.Properties.GetAll'; - const cancellable = this._cancelRefreshProperties({ - propertyName: cancellableName, - addNew: true, - }); - - try { - const [valuesVariant] = (await this.getProperties( - cancellable)).deep_unpack(); - - this._cancellables.delete(cancellableName); - - await Promise.all( - Object.entries(valuesVariant).map(([propertyName, valueVariant]) => - this._queuePropertyUpdate(propertyName, valueVariant, { - skipEqualityCheck: true, - cancellable, - }))); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - // the property may not even exist, silently ignore it - Util.Logger.debug(`While refreshing all properties: ${e}`); - - this.get_cached_property_names().forEach(propertyName => - this.set_cached_property(propertyName, null)); - - this._cancellables.delete(cancellableName); - throw e; - } - } - } - - async refreshProperty(propertyName, params) { - params = Params.parse(params, { - skipEqualityCheck: false, - }); - - const cancellable = this._cancelRefreshProperties({ - propertyName, - addNew: true, - }); - - try { - const [valueVariant] = (await this.getProperty( - propertyName, cancellable)).deep_unpack(); - - this._cancellables.delete(propertyName); - await this._queuePropertyUpdate(propertyName, valueVariant, - Object.assign(params, {cancellable})); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - // the property may not even exist, silently ignore it - Util.Logger.debug(`While refreshing property ${propertyName}: ${e}`); - this.set_cached_property(propertyName, null); - this._cancellables.delete(propertyName); - delete this._changedProperties[propertyName]; - throw e; - } - } - } - - async _queuePropertyUpdate(propertyName, value, params) { - params = Params.parse(params, { - skipEqualityCheck: false, - cancellable: null, - }); - - if (!params.skipEqualityCheck) { - const cachedProperty = this.get_cached_property(propertyName); - - if (value && cachedProperty && - value.equal(this.get_cached_property(propertyName))) - return; - } - - this.set_cached_property(propertyName, value); - - // synthesize a batched property changed event - this._changedProperties[propertyName] = value; - - if (!this._propertiesEmitTimeout || !this._propertiesEmitTimeout.pending()) { - if (!params.cancellable) { - params.cancellable = this._cancelRefreshProperties({ - propertyName, - addNew: true, - }); - } - this._propertiesEmitTimeout = new PromiseUtils.TimeoutPromise( - MAX_UPDATE_FREQUENCY * 2, GLib.PRIORITY_DEFAULT_IDLE, params.cancellable); - await this._propertiesEmitTimeout; - - if (Object.keys(this._changedProperties).length) { - this.emit('g-properties-changed', GLib.Variant.new('a{sv}', - this._changedProperties), []); - this._changedProperties = Object.create(null); - } - } - } - - _cancelRefreshProperties(params) { - params = Params.parse(params, { - propertyName: undefined, - addNew: false, - }); - - if (!this._cancellables.size && !params.addNew) - return null; - - if (params.propertyName !== undefined) { - let cancellable = this._cancellables.get(params.propertyName); - if (cancellable) { - cancellable.cancel(); - - if (!params.addNew) - this._cancellables.delete(params.propertyName); - } - - if (params.addNew) { - cancellable = new Util.CancellableChild(this._cancellable); - this._cancellables.set(params.propertyName, cancellable); - return cancellable; - } - } else { - this._cancellables.forEach(c => c.cancel()); - this._cancellables.clear(); - this._changedProperties = Object.create(null); - } - - return null; - } -}); - -/** - * the AppIndicator class serves as a generic container for indicator information and functions common - * for every displaying implementation (IndicatorMessageSource and IndicatorStatusIcon) - */ -export class AppIndicator extends Signals.EventEmitter { - static get NEEDED_PROPERTIES() { - return ['Id', 'Menu']; - } - - constructor(service, busName, object) { - super(); - - this.isReady = false; - this.busName = busName; - this._uniqueId = Util.indicatorId(service, busName, object); - - this._cancellable = new Gio.Cancellable(); - this._proxy = new AppIndicatorProxy(busName, object); - this._invalidatedPixmapsIcons = new Set(); - - this._setupProxy().catch(logError); - Util.connectSmart(this._proxy, 'g-properties-changed', this, this._onPropertiesChanged); - Util.connectSmart(this._proxy, 'notify::g-name-owner', this, this._nameOwnerChanged); - - if (this.uniqueId === service) { - this._nameWatcher = new Util.NameWatcher(service); - Util.connectSmart(this._nameWatcher, 'changed', this, this._nameOwnerChanged); - } - } - - async _setupProxy() { - const cancellable = this._cancellable; - - try { - await this._proxy.initAsync(cancellable); - this._checkIfReady(); - await this._checkNeededProperties(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - logError(e, `While initalizing proxy for ${this._uniqueId}`); - this.destroy(); - } - } - - try { - this._commandLine = await Util.getProcessName(this.busName, - cancellable, GLib.PRIORITY_LOW); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.debug( - `${this.uniqueId}, failed getting command line: ${e.message}`); - } - } - } - - _checkIfReady() { - const wasReady = this.isReady; - let isReady = false; - - if (this.hasNameOwner && this.id && this.menuPath) - isReady = true; - - this.isReady = isReady; - - if (this.isReady && !wasReady) { - if (this._delayCheck) { - this._delayCheck.cancel(); - delete this._delayCheck; - } - - this.emit('ready'); - return true; - } - - return false; - } - - async _checkNeededProperties() { - if (this.id && this.menuPath) - return true; - - const MAX_RETRIES = 3; - const cancellable = this._cancellable; - for (let checks = 0; checks < MAX_RETRIES; ++checks) { - this._delayCheck = new PromiseUtils.TimeoutSecondsPromise(1, - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - // eslint-disable-next-line no-await-in-loop - await this._delayCheck; - - try { - // eslint-disable-next-line no-await-in-loop - await Promise.all(AppIndicator.NEEDED_PROPERTIES.map(p => - this._proxy.refreshProperty(p))); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - - if (checks < MAX_RETRIES - 1) - continue; - - throw e; - } - - if (this.id && this.menuPath) - break; - } - - return this.id && this.menuPath; - } - - async _nameOwnerChanged() { - if (!this.hasNameOwner) { - this._checkIfReady(); - } else { - try { - await this._checkNeededProperties(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.warn(`${this.uniqueId}, Impossible to get basic properties: ${e}`); - this.checkAlive(); - } - } - } - - this.emit('name-owner-changed'); - } - - // public property getters - get title() { - return this._proxy.Title; - } - - get id() { - return this._proxy.Id; - } - - get uniqueId() { - return this._uniqueId; - } - - get status() { - return this._proxy.Status; - } - - get label() { - return this._proxy.XAyatanaLabel || null; - } - - get accessibleName() { - const accessibleDesc = this.status === SNIStatus.NEEDS_ATTENTION - ? this._proxy.AccessibleDesc : this._proxy.IconAccessibleDesc; - - return accessibleDesc || this.title; - } - - get menuPath() { - if (this._proxy.Menu === '/NO_DBUSMENU') - return null; - - return this._proxy.Menu; - } - - get attentionIcon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.AttentionIconName, - pixmap: this._getPixmapProperty(SNIconType.ATTENTION), - }; - } - - get icon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.IconName, - pixmap: this._getPixmapProperty(SNIconType.NORMAL), - }; - } - - get overlayIcon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.OverlayIconName, - pixmap: this._getPixmapProperty(SNIconType.OVERLAY), - }; - } - - get hasOverlayIcon() { - const {name, pixmap} = this.overlayIcon; - - return name || (pixmap && pixmap.n_children()); - } - - get hasNameOwner() { - if (this._nameWatcher && !this._nameWatcher.nameOnBus) - return false; - return !!this._proxy.g_name_owner; - } - - get cancellable() { - return this._cancellable; - } - - async checkAlive() { - // Some applications (hey electron!) just remove the indicator object - // from bus after hiding it, without closing its bus name, so we are - // not able to understand whe they're gone. - // Thus we just kill it when an expected well-known method is failing. - if (this.status !== SNIStatus.PASSIVE && this._checkIfReady()) { - if (this._checkAliveTimeout) { - this._checkAliveTimeout.cancel(); - delete this._checkAliveTimeout; - } - return; - } - - if (this._checkAliveTimeout) - return; - - try { - const cancellable = this._cancellable; - this._checkAliveTimeout = new PromiseUtils.TimeoutSecondsPromise(10, - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - Util.Logger.debug(`${this.uniqueId}: may not respond, checking...`); - await this._checkAliveTimeout; - - // We should call the Ping method instead but in some containers - // such as snaps that's not accessible, so let's just use our own - await this._proxy.getProperty('Status', cancellable); - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.NAME_HAS_NO_OWNER) || - e.matches(Gio.DBusError, Gio.DBusError.SERVICE_UNKNOWN) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_OBJECT) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_INTERFACE) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_PROPERTY)) { - Util.Logger.warn(`${this.uniqueId}: not on bus anymore, removing it`); - this.destroy(); - return; - } - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._checkAliveTimeout; - } - } - - _onPropertiesChanged(_proxy, changed, _invalidated) { - const props = Object.keys(changed.unpack()); - const signalsToEmit = new Set(); - const checkIfReadyChanged = () => { - if (checkIfReadyChanged.value === undefined) - checkIfReadyChanged.value = this._checkIfReady(); - return checkIfReadyChanged.value; - }; - - props.forEach(property => { - // some property changes require updates on our part, - // a few need to be passed down to the displaying code - if (property === 'Id') - checkIfReadyChanged(); - - // all these can mean that the icon has to be changed - if (property.startsWith('Icon') || - property.startsWith('AttentionIcon')) - signalsToEmit.add('icon'); - - // same for overlays - if (property.startsWith('OverlayIcon')) - signalsToEmit.add('overlay-icon'); - - // this may make all of our icons invalid - if (property === 'IconThemePath') { - signalsToEmit.add('icon'); - signalsToEmit.add('overlay-icon'); - } - - // the label will be handled elsewhere - if (property === 'XAyatanaLabel') - signalsToEmit.add('label'); - - if (property === 'Menu') { - if (!checkIfReadyChanged() && this.isReady) - signalsToEmit.add('menu'); - } - - if (property === 'IconAccessibleDesc' || - property === 'AttentionAccessibleDesc' || - property === 'Title') - signalsToEmit.add('accessible-name'); - - // status updates may cause the indicator to be hidden - if (property === 'Status') { - signalsToEmit.add('icon'); - signalsToEmit.add('overlay-icon'); - signalsToEmit.add('status'); - signalsToEmit.add('accessible-name'); - } - }); - - signalsToEmit.forEach(s => this.emit(s)); - } - - reset() { - this.emit('reset'); - } - - destroy() { - this.emit('destroy'); - - this.disconnectAll(); - this._proxy.destroy(); - this._cancellable.cancel(); - this._invalidatedPixmapsIcons.clear(); - - if (this._nameWatcher) - this._nameWatcher.destroy(); - delete this._cancellable; - delete this._proxy; - delete this._nameWatcher; - } - - _getPixmapProperty(iconType) { - const propertyName = SNIconType.toPropertyName(iconType, - {isPixbuf: true}); - const pixmap = this._proxy.get_cached_property(propertyName); - const wasInvalidated = this._invalidatedPixmapsIcons.delete(iconType); - - if (!pixmap && wasInvalidated) { - this._proxy.refreshProperty(propertyName, { - skipEqualityCheck: true, - }).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - return pixmap; - } - - invalidatePixmapProperty(iconType) { - this._invalidatedPixmapsIcons.add(iconType); - this._proxy.set_cached_property( - SNIconType.toPropertyName(iconType, {isPixbuf: true}), null); - } - - _getActivationToken(timestamp) { - const launchContext = global.create_app_launch_context(timestamp, -1); - const fakeAppInfo = Gio.AppInfo.create_from_commandline( - this._commandLine || 'true', this.id, - Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION); - return [launchContext, launchContext.get_startup_notify_id(fakeAppInfo, [])]; - } - - async provideActivationToken(timestamp) { - if (this._hasProvideXdgActivationToken === false) - return; - - const [launchContext, activationToken] = this._getActivationToken(timestamp); - try { - await this._proxy.ProvideXdgActivationTokenAsync(activationToken, - this._cancellable); - this._hasProvideXdgActivationToken = true; - } catch (e) { - launchContext.launch_failed(activationToken); - - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) - this._hasProvideXdgActivationToken = false; - else - Util.Logger.warn(`${this.id}, failed to provide activation token: ${e.message}`); - } - } - - async open(x, y, timestamp) { - const cancellable = this._cancellable; - // we can't use WindowID because we're not able to get the x11 window id from a MetaWindow - // nor can we call any X11 functions. Luckily, the Activate method usually works fine. - // parameters are "an hint to the item where to show eventual windows" [sic] - // ... and don't seem to have any effect. - - try { - await this.provideActivationToken(timestamp); - await this._proxy.ActivateAsync(x, y, cancellable); - this.supportsActivation = true; - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) { - this.supportsActivation = false; - Util.Logger.warn(`${this.id}, does not support activation: ${e.message}`); - return; - } - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.critical(`${this.id}, failed to activate: ${e.message}`); - } - } - - async secondaryActivate(timestamp, x, y) { - const cancellable = this._cancellable; - - try { - await this.provideActivationToken(timestamp); - - if (this._hasAyatanaSecondaryActivate !== false) { - try { - await this._proxy.XAyatanaSecondaryActivateAsync(timestamp, cancellable); - this._hasAyatanaSecondaryActivate = true; - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) - this._hasAyatanaSecondaryActivate = false; - else - throw e; - } - } - - if (!this._hasAyatanaSecondaryActivate) - await this._proxy.SecondaryActivateAsync(x, y, cancellable); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.critical(`${this.id}, failed to secondary activate: ${e.message}`); - } - } - - async scroll(dx, dy) { - const cancellable = this._cancellable; - - try { - const actions = []; - - if (dx !== 0) { - actions.push(this._proxy.ScrollAsync(Math.floor(dx), - 'horizontal', cancellable)); - } - - if (dy !== 0) { - actions.push(this._proxy.ScrollAsync(Math.floor(dy), - 'vertical', cancellable)); - } - - await Promise.all(actions); - } catch (e) { - Util.Logger.critical(`${this.id}, failed to scroll: ${e.message}`); - } - } -} - -const StTextureCacheSkippingFileIcon = GObject.registerClass({ - Implements: [Gio.Icon], -}, class StTextureCacheSkippingFileIconImpl extends Gio.EmblemedIcon { - _init(params) { - // FIXME: We can't just inherit from Gio.FileIcon for some reason - super._init({gicon: new Gio.FileIcon(params)}); - } - - vfunc_to_tokens() { - // Disables the to_tokens() vfunc so that the icon to_string() - // method won't work and thus can't be kept forever around by - // StTextureCache, see the awesome debugging session in this thread: - // https://twitter.com/mild_sunrise/status/1458739604098621443 - // upstream bug is at: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4944 - return [false, [], 0]; - } -}); - -export const IconActor = GObject.registerClass( -class AppIndicatorsIconActor extends St.Icon { - static get DEFAULT_STYLE() { - return 'padding: 0'; - } - - static get USER_WRITABLE_PATHS() { - if (!this._userWritablePaths) { - this._userWritablePaths = [ - GLib.get_user_cache_dir(), - GLib.get_user_data_dir(), - GLib.get_user_config_dir(), - GLib.get_user_runtime_dir(), - GLib.get_home_dir(), - GLib.get_tmp_dir(), - ]; - - this._userWritablePaths.push(Object.values(GLib.UserDirectory).slice( - 0, -1).map(dirId => GLib.get_user_special_dir(dirId))); - } - - return this._userWritablePaths; - } - - _init(indicator, iconSize) { - super._init({ - reactive: true, - style_class: 'system-status-icon', - fallbackIconName: FALLBACK_ICON_NAME, - }); - - this.name = this.constructor.name; - this.add_style_class_name('appindicator-icon'); - this.add_style_class_name('status-notifier-icon'); - this.set_style(AppIndicatorsIconActor.DEFAULT_STYLE); - - const themeContext = St.ThemeContext.get_for_stage(global.stage); - this.height = iconSize * themeContext.scale_factor; - - this._indicator = indicator; - this._customIcons = new Map(); - this._iconSize = iconSize; - this._iconCache = new IconCache.IconCache(); - this._cancellable = new Gio.Cancellable(); - this._loadingIcons = Object.create(null); - - Object.values(SNIconType).forEach(t => (this._loadingIcons[t] = new Map())); - - Util.connectSmart(this._indicator, 'icon', this, () => { - if (this.is_mapped()) - this._updateIcon(); - }); - Util.connectSmart(this._indicator, 'overlay-icon', this, () => { - if (this.is_mapped()) - this._updateIcon(); - }); - Util.connectSmart(this._indicator, 'reset', this, - () => this._invalidateIconWhenFullyReady()); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-size', this, () => - this._updateWhenFullyReady()); - Util.connectSmart(settings, 'changed::custom-icons', this, () => { - this._updateCustomIcons(); - this._invalidateIconWhenFullyReady(); - }); - - if (GObject.signal_lookup('resource-scale-changed', this)) - this.connect('resource-scale-changed', () => this._invalidateIcon()); - else - this.connect('notify::resource-scale', () => this._invalidateIcon()); - - Util.connectSmart(themeContext, 'notify::scale-factor', this, tc => { - this._updateIconSize(); - this.height = this._iconSize * tc.scale_factor; - this.width = -1; - this._invalidateIcon(); - }); - - Util.connectSmart(Util.getDefaultTheme(), 'changed', this, - () => this._invalidateIconWhenFullyReady()); - - this.connect('notify::mapped', () => { - if (!this.is_mapped()) - this._updateWhenFullyReady(); - }); - - this._updateWhenFullyReady(); - - this.connect('destroy', () => { - this._iconCache.destroy(); - this._cancellable.cancel(); - this._cancellable = null; - this._indicator = null; - this._loadingIcons = null; - this._iconTheme = null; - }); - } - - get debugId() { - return this._indicator ? this._indicator.id : this.toString(); - } - - async _waitForFullyReady() { - const waitConditions = []; - - if (!this.is_mapped()) { - waitConditions.push(new PromiseUtils.SignalConnectionPromise( - this, 'notify::mapped', this._cancellable)); - } - - if (!this._indicator.isReady) { - waitConditions.push(new PromiseUtils.SignalConnectionPromise( - this._indicator, 'ready', this._cancellable)); - } - - if (!waitConditions.length) - return true; - - await Promise.all(waitConditions); - return this._waitForFullyReady(); - } - - async _updateWhenFullyReady() { - if (this._waitingReady) - return; - - try { - this._waitingReady = true; - await this._waitForFullyReady(); - - this._updateIconSize(); - this._updateIconClass(); - this._updateCustomIcons(); - this._invalidateIcon(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._waitingReady; - } - } - - _updateIconClass() { - if (!this._indicator) - return; - - this.add_style_class_name( - `appindicator-icon-${this._indicator.id.toLowerCase().replace(/_|\s/g, '-')}`); - } - - _cancelLoadingByType(iconType) { - this._loadingIcons[iconType].forEach(c => c.cancel()); - this._loadingIcons[iconType].clear(); - } - - _ensureNoIconIsLoading(iconType, id) { - if (this._loadingIcons[iconType].has(id)) { - Util.Logger.debug(`${this.debugId}, Icon ${id} Is still loading, ignoring the request`); - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING, - 'Already in progress'); - } else if (this._loadingIcons[iconType].size > 0) { - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS, - 'Another icon is already loading'); - } - } - - _getIconLoadingCancellable(iconType, loadingId) { - try { - this._ensureNoIconIsLoading(iconType, loadingId); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) - throw e; - this._cancelLoadingByType(iconType); - } - - const cancellable = new Util.CancellableChild(this._cancellable); - this._loadingIcons[iconType].set(loadingId, cancellable); - - return cancellable; - } - - _cleanupIconLoadingCancellable(iconType, loadingId) { - if (this._loadingIcons) - this._loadingIcons[iconType].delete(loadingId); - } - - _getResourceScale() { - // Remove this when we remove support for versions earlier than 3.38 - const resourceScale = this.get_resource_scale(); - if (Array.isArray(resourceScale)) - return resourceScale[0] ? resourceScale[1] : 1.0; - - return resourceScale; - } - - // Will look the icon up in the cache, if it's found - // it will return it. Otherwise, it will create it and cache it. - async _cacheOrCreateIconByName(iconType, iconSize, iconScaling, iconName, themePath) { - const id = `${iconType}:${iconName}@${iconSize * iconScaling}:${themePath || ''}`; - let gicon = this._iconCache.get(id); - - if (gicon) - return gicon; - - const iconData = this._getIconData(iconName, themePath, iconSize, iconScaling); - const loadingId = iconData.file ? iconData.file.get_path() : id; - - const cancellable = await this._getIconLoadingCancellable(iconType, id); - try { - gicon = await this._createIconByIconData(iconData, iconSize, - iconScaling, cancellable); - } finally { - this._cleanupIconLoadingCancellable(iconType, loadingId); - } - if (gicon) - gicon = this._iconCache.add(id, gicon); - return gicon; - } - - _getIconLookupFlags(themeNode) { - let lookupFlags = 0; - - if (!themeNode) - return lookupFlags; - - const lookupFlagsEnum = St.IconLookupFlags; - const iconStyle = themeNode.get_icon_style(); - if (iconStyle === St.IconStyle.REGULAR) - lookupFlags |= lookupFlagsEnum.FORCE_REGULAR; - else if (iconStyle === St.IconStyle.SYMBOLIC) - lookupFlags |= lookupFlagsEnum.FORCE_SYMBOLIC; - - if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) - lookupFlags |= lookupFlagsEnum.DIR_RTL; - else - lookupFlags |= lookupFlagsEnum.DIR_LTR; - - return lookupFlags; - } - - async _createIconByIconData(iconData, iconSize, iconScaling, cancellable) { - const {file, name} = iconData; - - if (!file && !name) { - if (this._createIconIdle) { - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING, - 'Already in progress'); - } - - try { - this._createIconIdle = new PromiseUtils.IdlePromise(GLib.PRIORITY_DEFAULT_IDLE, - cancellable); - await this._createIconIdle; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - throw e; - } finally { - delete this._createIconIdle; - } - return this.gicon; - } else if (this._createIconIdle) { - this._createIconIdle.cancel(); - delete this._createIconIdle; - } - - if (name) - return new Gio.ThemedIcon({name}); - - if (!file) - throw new Error('Neither file or name are set'); - - if (!this._isFileInWritableArea(file)) - return new Gio.FileIcon({file}); - - try { - const [format, width, height] = await GdkPixbuf.Pixbuf.get_file_info_async( - file.get_path(), cancellable); - - if (!format) { - Util.Logger.critical(`${this.debugId}, Invalid image format: ${file.get_path()}`); - return null; - } - - if (width >= height * 1.5) { - /* Hello indicator-multiload! */ - await this._loadCustomImage(file, - width, height, iconSize, iconScaling, cancellable); - return null; - } else { - /* We'll wrap the icon so that it won't be cached forever by the shell */ - return new StTextureCacheSkippingFileIcon({file}); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.warn( - `${this.debugId}, Impossible to read image info from ` + - `path '${file ? file.get_path() : null}' or name '${name}': ${e}`); - } - throw e; - } - } - - async _loadCustomImage(file, width, height, iconSize, iconScaling, cancellable) { - const textureCache = St.TextureCache.get_default(); - const customImage = textureCache.load_file_async(file, -1, - height, 1, iconScaling); - - const setCustomImageActor = imageActor => { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const {content} = imageActor; - imageActor.content = null; - imageActor.destroy(); - - this._setImageContent(content, - width * scaleFactor, height * scaleFactor); - }; - - if (customImage.content) { - setCustomImageActor(customImage); - return; - } - - const imageContentPromise = new PromiseUtils.SignalConnectionPromise( - customImage, 'notify::content', cancellable); - const waitPromise = new PromiseUtils.TimeoutSecondsPromise( - 1, GLib.PRIORITY_DEFAULT, cancellable); - - const racingPromises = [imageContentPromise, waitPromise]; - - try { - await Promise.race(racingPromises); - if (!waitPromise.resolved()) - setCustomImageActor(customImage); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - racingPromises.forEach(p => p.cancel()); - } - } - - _isFileInWritableArea(file) { - // No need to use IO here, we can just do some assumptions - // print('Writable paths', IconActor.USER_WRITABLE_PATHS) - const path = file.get_path(); - return IconActor.USER_WRITABLE_PATHS.some(writablePath => - path.startsWith(writablePath)); - } - - _createIconTheme(searchPath = []) { - const iconTheme = new St.IconTheme(); - iconTheme.set_search_path(searchPath); - - return iconTheme; - } - - _getIconData(name, themePath, size, scale) { - const emptyIconData = {iconInfo: null, file: null, name: null}; - - if (!name) { - delete this._iconTheme; - return emptyIconData; - } - - // HACK: icon is a path name. This is not specified by the API, - // but at least indicator-sensors uses it. - if (name[0] === '/') { - delete this._iconTheme; - - const file = Gio.File.new_for_path(name); - return {file, iconInfo: null, name: null}; - } - - if (name.includes('.')) { - const splits = name.split('.'); - - if (['svg', 'png'].includes(splits[splits.length - 1])) - name = splits.slice(0, -1).join(''); - } - - if (themePath && Util.getDefaultTheme().get_search_path().includes(themePath)) - themePath = null; - - if (themePath) { - // If a theme path is provided, we need to lookup the icon ourself - // as St won't be able to do it unless we mess with default theme - // that is something we prefer not to do, as it would imply lots of - // St.TextureCache cleanups. - - const newSearchPath = [themePath]; - if (!this._iconTheme) { - this._iconTheme = this._createIconTheme(newSearchPath); - } else { - const currentSearchPath = this._iconTheme.get_search_path(); - - if (!currentSearchPath.includes(newSearchPath)) - this._iconTheme.set_search_path(newSearchPath); - } - - // try to look up the icon in the icon theme - const iconInfo = this._iconTheme.lookup_icon_for_scale(`${name}`, - size, scale, this._getIconLookupFlags(this.get_theme_node()) | - St.IconLookupFlags.GENERIC_FALLBACK); - - if (iconInfo) { - return { - iconInfo, - file: Gio.File.new_for_path(iconInfo.get_filename()), - name: null, - }; - } - - const logger = this.gicon ? Util.Logger.debug : Util.Logger.warn; - logger(`${this.debugId}, Impossible to lookup icon ` + - `for '${name}' in ${themePath}`); - - return emptyIconData; - } - - delete this._iconTheme; - return {name, iconInfo: null, file: null}; - } - - _setImageContent(content, width, height) { - this.set({ - content, - width, - height, - contentGravity: Clutter.ContentGravity.RESIZE_ASPECT, - fallbackIconName: null, - }); - } - - async _createIconFromPixmap(iconType, iconSize, iconScaling, scaleFactor, pixmapsVariant) { - const {pixmapVariant, width, height, rowStride} = - PixmapsUtils.getBestPixmap(pixmapsVariant, iconSize * iconScaling); - - const id = `__PIXMAP_ICON_${width}x${height}`; - - const imageContent = new St.ImageContent({ - preferredWidth: width, - preferredHeight: height, - }); - - imageContent.set_bytes(pixmapVariant.get_data_as_bytes(), PIXMAPS_FORMAT, - width, height, rowStride); - - if (iconType !== SNIconType.OVERLAY && !this._indicator.hasOverlayIcon) { - const scaledSize = iconSize * scaleFactor; - this._setImageContent(imageContent, scaledSize, scaledSize); - return null; - } - - const cancellable = this._getIconLoadingCancellable(iconType, id); - try { - // FIXME: async API results in a gray icon for some reason - const [inputStream] = imageContent.load(iconSize, cancellable); - return await GdkPixbuf.Pixbuf.new_from_stream_at_scale_async( - inputStream, -1, iconSize * iconScaling, true, cancellable); - } catch (e) { - // the image data was probably bogus. We don't really know why, but it _does_ happen. - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`${this.debugId}, Impossible to create image from data: ${e}`); - throw e; - } finally { - this._cleanupIconLoadingCancellable(iconType, id); - } - } - - // The icon cache Active flag will be set to true if the used gicon matches - // the cached one (as in some cases it may be equal, but not the same object). - // So when it's not need anymore we make sure to check the active state - // and set it to false so that it can be picked up by the garbage collector. - _setGicon(iconType, gicon) { - if (iconType !== SNIconType.OVERLAY) { - if (gicon) { - if (this.gicon === gicon || - (this.gicon && this.gicon.get_icon() === gicon)) - return; - - if (gicon instanceof Gio.EmblemedIcon) - this.gicon = gicon; - else - this.gicon = new Gio.EmblemedIcon({gicon}); - - this._iconCache.updateActive(SNIconType.NORMAL, gicon, - this.gicon.get_icon() === gicon); - } else { - this.gicon = null; - } - } else if (gicon) { - this._emblem = new Gio.Emblem({icon: gicon}); - this._iconCache.updateActive(iconType, gicon, true); - } else { - this._emblem = null; - } - - if (this.gicon) { - if (!this.gicon.get_emblems().some(e => e.equal(this._emblem))) { - this.gicon.clear_emblems(); - if (this._emblem) - this.gicon.add_emblem(this._emblem); - } - } - } - - async _updateIconByType(iconType, iconSize) { - let icon; - switch (iconType) { - case SNIconType.ATTENTION: - icon = this._indicator.attentionIcon; - break; - case SNIconType.NORMAL: - ({icon} = this._indicator); - break; - case SNIconType.OVERLAY: - icon = this._indicator.overlayIcon; - break; - } - - const {theme, name, pixmap} = icon; - const commonArgs = [theme, iconType, iconSize]; - - if (this._customIcons.size) { - let customIcon = this._customIcons.get(iconType); - if (!await this._createAndSetIcon(customIcon, null, ...commonArgs)) { - if (iconType !== SNIconType.OVERLAY) { - customIcon = this._customIcons.get(SNIconType.NORMAL); - await this._createAndSetIcon(customIcon, null, ...commonArgs); - } - } - } else { - await this._createAndSetIcon(name, pixmap, ...commonArgs); - } - } - - async _createAndSetIcon(name, pixmap, theme, iconType, iconSize) { - let gicon = null; - - try { - gicon = await this._createIcon(name, pixmap, theme, iconType, iconSize); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) || - e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - return null; - - if (iconType === SNIconType.OVERLAY) { - logError(e, `${this.debugId} unable to update icon emblem`); - } else { - this.fallbackIconName = FALLBACK_ICON_NAME; - logError(e, `${this.debugId} unable to update icon`); - } - } - - try { - this._setGicon(iconType, gicon); - - if (pixmap && this.gicon) { - // The pixmap has been saved, we can free the variants memory - this._indicator.invalidatePixmapProperty(iconType); - } - - return gicon; - } catch (e) { - logError(e, 'Setting GIcon failed'); - return null; - } - } - - // updates the base icon - async _createIcon(name, pixmap, theme, iconType, iconSize) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const resourceScale = this._getResourceScale(); - const iconScaling = Math.ceil(resourceScale * scaleFactor); - - // From now on we consider them the same thing, as one replaces the other - if (iconType === SNIconType.ATTENTION) - iconType = SNIconType.NORMAL; - - if (name) { - const gicon = await this._cacheOrCreateIconByName( - iconType, iconSize, iconScaling, name, theme); - if (gicon) - return gicon; - } - - if (pixmap && pixmap.n_children()) { - return this._createIconFromPixmap(iconType, - iconSize, iconScaling, scaleFactor, pixmap); - } - - return null; - } - - // updates the base icon - async _updateIcon() { - if (this._indicator.status === SNIStatus.PASSIVE) - return; - - if (this.gicon instanceof Gio.EmblemedIcon) { - const {gicon} = this.gicon; - this._iconCache.updateActive(SNIconType.NORMAL, gicon, false); - } - - // we might need to use the AttentionIcon*, which have precedence over the normal icons - const iconType = this._indicator.status === SNIStatus.NEEDS_ATTENTION - ? SNIconType.ATTENTION : SNIconType.NORMAL; - - try { - await this._updateIconByType(iconType, this._iconSize); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) && - !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - logError(e, `${this.debugId}: Updating icon type ${iconType} failed`); - } - } - - async _updateOverlayIcon() { - if (this._indicator.status === SNIStatus.PASSIVE) - return; - - if (this._emblem) { - const {icon} = this._emblem; - this._iconCache.updateActive(SNIconType.OVERLAY, icon, false); - } - - // KDE hardcodes the overlay icon size to 10px (normal icon size 16px) - // we approximate that ratio for other sizes, too. - // our algorithms will always pick a smaller one instead of stretching it. - const iconSize = Math.floor(this._iconSize / 1.6); - - try { - await this._updateIconByType(SNIconType.OVERLAY, iconSize); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) && - !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - logError(e, `${this.debugId}: Updating overlay icon failed`); - } - } - - async _invalidateIconWhenFullyReady() { - if (this._waitingInvalidation) - return; - - try { - this._waitingInvalidation = true; - await this._waitForFullyReady(); - this._invalidateIcon(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._waitingInvalidation; - } - } - - // called when the icon theme changes - _invalidateIcon() { - this._iconCache.clear(); - this._cancellable.cancel(); - this._cancellable = new Gio.Cancellable(); - Object.values(SNIconType).forEach(iconType => - this._loadingIcons[iconType].clear()); - - this._updateIcon().catch(e => logError(e)); - this._updateOverlayIcon().catch(e => logError(e)); - } - - _updateIconSize() { - const settings = SettingsManager.getDefaultGSettings(); - const sizeValue = settings.get_int('icon-size'); - - if (sizeValue > 0) { - if (!this._defaultIconSize) - this._defaultIconSize = this._iconSize; - - this._iconSize = sizeValue; - } else if (this._defaultIconSize) { - this._iconSize = this._defaultIconSize; - delete this._defaultIconSize; - } - - const themeIconSize = Math.round( - this.get_theme_node().get_length('icon-size')); - let iconStyle = AppIndicatorsIconActor.DEFAULT_STYLE; - - if (themeIconSize > 0) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - - if (themeIconSize / scaleFactor !== this._iconSize) { - iconStyle = `${AppIndicatorsIconActor.DEFAULT_STYLE};` + - 'icon-size: 0'; - } - } - - this.set_style(iconStyle); - this.set_icon_size(this._iconSize); - } - - _updateCustomIcons() { - const settings = SettingsManager.getDefaultGSettings(); - this._customIcons.clear(); - - settings.get_value('custom-icons').deep_unpack().forEach(customIcons => { - const [indicatorId, normalIcon, attentionIcon] = customIcons; - if (this._indicator.id === indicatorId) { - this._customIcons.set(SNIconType.NORMAL, normalIcon); - this._customIcons.set(SNIconType.ATTENTION, attentionIcon); - } - }); - } -}); diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js deleted file mode 100644 index 4f9467f..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js +++ /dev/null @@ -1,950 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import St from 'gi://St'; - -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as DBusInterfaces from './interfaces.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; -import {DBusProxy} from './dbusProxy.js'; - -Gio._promisify(GdkPixbuf.Pixbuf, 'new_from_stream_async'); - -// //////////////////////////////////////////////////////////////////////// -// PART ONE: "ViewModel" backend implementation. -// Both code and design are inspired by libdbusmenu -// //////////////////////////////////////////////////////////////////////// - -/** - * Saves menu property values and handles type checking and defaults - */ -export class PropertyStore { - constructor(initialProperties) { - this._props = new Map(); - - if (initialProperties) { - for (const [prop, value] of Object.entries(initialProperties)) - this.set(prop, value); - } - } - - set(name, value) { - if (name in PropertyStore.MandatedTypes && value && - !value.is_of_type(PropertyStore.MandatedTypes[name])) - Util.Logger.warn(`Cannot set property ${name}: type mismatch!`); - else if (value) - this._props.set(name, value); - else - this._props.delete(name); - } - - get(name) { - const prop = this._props.get(name); - if (prop) - return prop; - else if (name in PropertyStore.DefaultValues) - return PropertyStore.DefaultValues[name]; - else - return null; - } -} - -// we list all the properties we know and use here, so we won' have to deal with unexpected type mismatches -PropertyStore.MandatedTypes = { - 'visible': GLib.VariantType.new('b'), - 'enabled': GLib.VariantType.new('b'), - 'label': GLib.VariantType.new('s'), - 'type': GLib.VariantType.new('s'), - 'children-display': GLib.VariantType.new('s'), - 'icon-name': GLib.VariantType.new('s'), - 'icon-data': GLib.VariantType.new('ay'), - 'toggle-type': GLib.VariantType.new('s'), - 'toggle-state': GLib.VariantType.new('i'), -}; - -PropertyStore.DefaultValues = { - 'visible': GLib.Variant.new_boolean(true), - 'enabled': GLib.Variant.new_boolean(true), - 'label': GLib.Variant.new_string(''), - 'type': GLib.Variant.new_string('standard'), - // elements not in here must return null -}; - -/** - * Represents a single menu item - */ -export class DbusMenuItem extends Signals.EventEmitter { - // will steal the properties object - constructor(client, id, properties, childrenIds) { - super(); - - this._client = client; - this._id = id; - this._propStore = new PropertyStore(properties); - this._children_ids = childrenIds; - } - - propertyGet(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_string()[0] : null; - } - - propertyGetVariant(propName) { - return this._propStore.get(propName); - } - - propertyGetBool(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_boolean() : false; - } - - propertyGetInt(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_int32() : 0; - } - - propertySet(prop, value) { - this._propStore.set(prop, value); - - this.emit('property-changed', prop, this.propertyGetVariant(prop)); - } - - getChildrenIds() { - return this._children_ids.concat(); // clone it! - } - - addChild(pos, childId) { - this._children_ids.splice(pos, 0, childId); - this.emit('child-added', this._client.getItem(childId), pos); - } - - removeChild(childId) { - // find it - let pos = -1; - for (let i = 0; i < this._children_ids.length; ++i) { - if (this._children_ids[i] === childId) { - pos = i; - break; - } - } - - if (pos < 0) { - Util.Logger.critical("Trying to remove child which doesn't exist"); - } else { - this._children_ids.splice(pos, 1); - this.emit('child-removed', this._client.getItem(childId)); - } - } - - moveChild(childId, newPos) { - // find the old position - let oldPos = -1; - for (let i = 0; i < this._children_ids.length; ++i) { - if (this._children_ids[i] === childId) { - oldPos = i; - break; - } - } - - if (oldPos < 0) { - Util.Logger.critical("tried to move child which wasn't in the list"); - return; - } - - if (oldPos !== newPos) { - this._children_ids.splice(oldPos, 1); - this._children_ids.splice(newPos, 0, childId); - this.emit('child-moved', oldPos, newPos, this._client.getItem(childId)); - } - } - - getChildren() { - return this._children_ids.map(el => this._client.getItem(el)); - } - - handleEvent(event, data, timestamp) { - if (!data) - data = GLib.Variant.new_int32(0); - - this._client.sendEvent(this._id, event, data, timestamp); - } - - getId() { - return this._id; - } - - sendAboutToShow() { - this._client.sendAboutToShow(this._id); - } -} - - -/** - * The client does the heavy lifting of actually reading layouts and distributing events - */ - -export const DBusClient = GObject.registerClass({ - Signals: {'ready-changed': {}}, -}, class AppIndicatorsDBusClient extends DBusProxy { - static get interfaceInfo() { - if (!this._interfaceInfo) { - this._interfaceInfo = Gio.DBusInterfaceInfo.new_for_xml( - DBusInterfaces.DBusMenu); - } - return this._interfaceInfo; - } - - static get baseItems() { - if (!this._baseItems) { - this._baseItems = { - 'children-display': GLib.Variant.new_string('submenu'), - }; - } - return this._baseItems; - } - - static destroy() { - delete this._interfaceInfo; - } - - _init(busName, objectPath) { - const {interfaceInfo} = AppIndicatorsDBusClient; - - super._init(busName, objectPath, interfaceInfo, - Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES); - - this._items = new Map(); - this._items.set(0, new DbusMenuItem(this, 0, DBusClient.baseItems, [])); - this._flagItemsUpdateRequired = false; - - // will be set to true if a layout update is needed once active - this._flagLayoutUpdateRequired = false; - - // property requests are queued - this._propertiesRequestedFor = new Set(/* ids */); - - this._layoutUpdated = false; - this._active = false; - } - - async initAsync(cancellable) { - await super.initAsync(cancellable); - - this._requestLayoutUpdate(); - } - - _onNameOwnerChanged() { - if (this.isReady) - this._requestLayoutUpdate(); - } - - get isReady() { - return this._layoutUpdated && !!this.gNameOwner; - } - - get cancellable() { - return this._cancellable; - } - - getRoot() { - return this._items.get(0); - } - - _requestLayoutUpdate() { - const cancellable = new Util.CancellableChild(this._cancellable); - this._beginLayoutUpdate(cancellable); - } - - async _requestProperties(propertyId, cancellable) { - this._propertiesRequestedFor.add(propertyId); - - if (this._propertiesRequest && this._propertiesRequest.pending()) - return; - - // if we don't have any requests queued, we'll need to add one - this._propertiesRequest = new PromiseUtils.IdlePromise( - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - await this._propertiesRequest; - - const requestedProperties = Array.from(this._propertiesRequestedFor); - this._propertiesRequestedFor.clear(); - const [result] = await this.GetGroupPropertiesAsync(requestedProperties, - [], cancellable); - - result.forEach(([id, properties]) => { - const item = this._items.get(id); - if (!item) - return; - - for (const [prop, value] of Object.entries(properties)) - item.propertySet(prop, value); - }); - } - - // Traverses the list of cached menu items and removes everyone that is not in the list - // so we don't keep alive unused items - _gcItems() { - const tag = new Date().getTime(); - - const toTraverse = [0]; - while (toTraverse.length > 0) { - const item = this.getItem(toTraverse.shift()); - item._dbusClientGcTag = tag; - Array.prototype.push.apply(toTraverse, item.getChildrenIds()); - } - - this._items.forEach((i, id) => { - if (i._dbusClientGcTag !== tag) - this._items.delete(id); - }); - } - - // the original implementation will only request partial layouts if somehow possible - // we try to save us from multiple kinds of race conditions by always requesting a full layout - _beginLayoutUpdate(cancellable) { - this._layoutUpdateUpdateAsync(cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - // the original implementation will only request partial layouts if somehow possible - // we try to save us from multiple kinds of race conditions by always requesting a full layout - async _layoutUpdateUpdateAsync(cancellable) { - // we only read the type property, because if the type changes after reading all properties, - // the view would have to replace the item completely which we try to avoid - if (this._layoutUpdateCancellable) - this._layoutUpdateCancellable.cancel(); - - this._layoutUpdateCancellable = cancellable; - - try { - const [revision_, root] = await this.GetLayoutAsync(0, -1, - ['type', 'children-display'], cancellable); - - this._updateLayoutState(true); - this._doLayoutUpdate(root, cancellable); - this._gcItems(); - this._flagLayoutUpdateRequired = false; - this._flagItemsUpdateRequired = false; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - this._updateLayoutState(false); - throw e; - } finally { - if (this._layoutUpdateCancellable === cancellable) - this._layoutUpdateCancellable = null; - } - } - - _updateLayoutState(state) { - const wasReady = this.isReady; - this._layoutUpdated = state; - if (this.isReady !== wasReady) - this.emit('ready-changed'); - } - - _doLayoutUpdate(item, cancellable) { - const [id, properties, children] = item; - - const childrenUnpacked = children.map(c => c.deep_unpack()); - const childrenIds = childrenUnpacked.map(([c]) => c); - - // make sure all our children exist - childrenUnpacked.forEach(c => this._doLayoutUpdate(c, cancellable)); - - // make sure we exist - const menuItem = this._items.get(id); - - if (menuItem) { - // we do, update our properties if necessary - for (const [prop, value] of Object.entries(properties)) - menuItem.propertySet(prop, value); - - // make sure our children are all at the right place, and exist - const oldChildrenIds = menuItem.getChildrenIds(); - for (let i = 0; i < childrenIds.length; ++i) { - // try to recycle an old child - let oldChild = -1; - for (let j = 0; j < oldChildrenIds.length; ++j) { - if (oldChildrenIds[j] === childrenIds[i]) { - [oldChild] = oldChildrenIds.splice(j, 1); - break; - } - } - - if (oldChild < 0) { - // no old child found, so create a new one! - menuItem.addChild(i, childrenIds[i]); - } else { - // old child found, reuse it! - menuItem.moveChild(childrenIds[i], i); - } - } - - // remove any old children that weren't reused - oldChildrenIds.forEach(c => menuItem.removeChild(c)); - - if (!this._flagItemsUpdateRequired) - return id; - } - - // we don't, so let's create us - let newMenuItem = menuItem; - - if (!newMenuItem) { - newMenuItem = new DbusMenuItem(this, id, properties, childrenIds); - this._items.set(id, newMenuItem); - } - - this._requestProperties(id, cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`Could not get menu properties menu proxy: ${e}`); - }); - - return id; - } - - async _doPropertiesUpdateAsync(cancellable) { - if (this._propertiesUpdateCancellable) - this._propertiesUpdateCancellable.cancel(); - - this._propertiesUpdateCancellable = cancellable; - - try { - const requests = []; - - this._items.forEach((_, id) => - requests.push(this._requestProperties(id, cancellable))); - - await Promise.all(requests); - } finally { - if (this._propertiesUpdateCancellable === cancellable) - this._propertiesUpdateCancellable = null; - } - } - - _doPropertiesUpdate() { - const cancellable = new Util.CancellableChild(this._cancellable); - this._doPropertiesUpdateAsync(cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`Could not get menu properties menu proxy: ${e}`); - }); - } - - - set active(active) { - const wasActive = this._active; - this._active = active; - - if (active && wasActive !== active) { - if (this._flagLayoutUpdateRequired) { - this._requestLayoutUpdate(); - } else if (this._flagItemsUpdateRequired) { - this._doPropertiesUpdate(); - this._flagItemsUpdateRequired = false; - } - } - } - - _onSignal(_sender, signal, params) { - if (signal === 'LayoutUpdated') { - if (!this._active) { - this._flagLayoutUpdateRequired = true; - return; - } - - this._requestLayoutUpdate(); - } else if (signal === 'ItemsPropertiesUpdated') { - if (!this._active) { - this._flagItemsUpdateRequired = true; - return; - } - - this._onPropertiesUpdated(params.deep_unpack()); - } - } - - getItem(id) { - const item = this._items.get(id); - if (!item) - Util.Logger.warn(`trying to retrieve item for non-existing id ${id} !?`); - return item || null; - } - - // we don't need to cache and burst-send that since it will not happen that frequently - async sendAboutToShow(id) { - /* Some indicators (you, dropbox!) don't use the right signature - * and don't return a boolean, so we need to support both cases */ - try { - const ret = await this.gConnection.call(this.gName, this.gObjectPath, - this.gInterfaceName, 'AboutToShow', new GLib.Variant('(i)', [id]), - null, Gio.DBusCallFlags.NONE, -1, this._cancellable); - - if ((ret.is_of_type(new GLib.VariantType('(b)')) && - ret.get_child_value(0).get_boolean()) || - ret.is_of_type(new GLib.VariantType('()'))) - this._requestLayoutUpdate(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - - sendEvent(id, event, params, timestamp) { - if (!this.gNameOwner) - return; - - this.EventAsync(id, event, params, timestamp, this._cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - _onPropertiesUpdated([changed, removed]) { - changed.forEach(([id, props]) => { - const item = this._items.get(id); - if (!item) - return; - - for (const [prop, value] of Object.entries(props)) - item.propertySet(prop, value); - }); - removed.forEach(([id, propNames]) => { - const item = this._items.get(id); - if (!item) - return; - - propNames.forEach(propName => item.propertySet(propName, null)); - }); - } -}); - -// //////////////////////////////////////////////////////////////////////// -// PART TWO: "View" frontend implementation. -// //////////////////////////////////////////////////////////////////////// - -// https://bugzilla.gnome.org/show_bug.cgi?id=731514 -// GNOME 3.10 and 3.12 can't open a nested submenu. -// Patches have been written, but it's not clear when (if?) they will be applied. -// We also don't know whether they will be backported to 3.10, so we will work around -// it in the meantime. Offending versions can be clearly identified: -const NEED_NESTED_SUBMENU_FIX = '_setOpenedSubMenu' in PopupMenu.PopupMenu.prototype; - -/** - * Creates new wrapper menu items and injects methods for managing them at runtime. - * - * Many functions in this object will be bound to the created item and executed as event - * handlers, so any `this` will refer to a menu item create in createItem - */ -const MenuItemFactory = { - createItem(client, dbusItem) { - // first, decide whether it's a submenu or not - let shellItem; - if (dbusItem.propertyGet('children-display') === 'submenu') - shellItem = new PopupMenu.PopupSubMenuMenuItem('FIXME'); - else if (dbusItem.propertyGet('type') === 'separator') - shellItem = new PopupMenu.PopupSeparatorMenuItem(''); - else - shellItem = new PopupMenu.PopupMenuItem('FIXME'); - - shellItem._dbusItem = dbusItem; - shellItem._dbusClient = client; - - if (shellItem instanceof PopupMenu.PopupMenuItem) { - shellItem._icon = new St.Icon({ - style_class: 'popup-menu-icon', - xAlign: Clutter.ActorAlign.END, - }); - shellItem.add_child(shellItem._icon); - shellItem.label.x_expand = true; - } - - // initialize our state - MenuItemFactory._updateLabel.call(shellItem); - MenuItemFactory._updateOrnament.call(shellItem); - MenuItemFactory._updateImage.call(shellItem); - MenuItemFactory._updateVisible.call(shellItem); - MenuItemFactory._updateSensitive.call(shellItem); - - // initially create children - if (shellItem instanceof PopupMenu.PopupSubMenuMenuItem) { - dbusItem.getChildren().forEach(c => - shellItem.menu.addMenuItem(MenuItemFactory.createItem(client, c))); - } - - // now, connect various events - Util.connectSmart(dbusItem, 'property-changed', - shellItem, MenuItemFactory._onPropertyChanged); - Util.connectSmart(dbusItem, 'child-added', - shellItem, MenuItemFactory._onChildAdded); - Util.connectSmart(dbusItem, 'child-removed', - shellItem, MenuItemFactory._onChildRemoved); - Util.connectSmart(dbusItem, 'child-moved', - shellItem, MenuItemFactory._onChildMoved); - Util.connectSmart(shellItem, 'activate', - shellItem, MenuItemFactory._onActivate); - - shellItem.connect('destroy', () => { - shellItem._dbusItem = null; - shellItem._dbusClient = null; - shellItem._icon = null; - }); - - if (shellItem.menu) { - Util.connectSmart(shellItem.menu, 'open-state-changed', - shellItem, MenuItemFactory._onOpenStateChanged); - } - - return shellItem; - }, - - _onOpenStateChanged(menu, open) { - if (open) { - if (NEED_NESTED_SUBMENU_FIX) { - // close our own submenus - if (menu._openedSubMenu) - menu._openedSubMenu.close(false); - - // register ourselves and close sibling submenus - if (menu._parent._openedSubMenu && menu._parent._openedSubMenu !== menu) - menu._parent._openedSubMenu.close(true); - - menu._parent._openedSubMenu = menu; - } - - this._dbusItem.handleEvent('opened', null, 0); - this._dbusItem.sendAboutToShow(); - } else { - if (NEED_NESTED_SUBMENU_FIX) { - // close our own submenus - if (menu._openedSubMenu) - menu._openedSubMenu.close(false); - } - - this._dbusItem.handleEvent('closed', null, 0); - } - }, - - _onActivate(_item, event) { - const timestamp = event.get_time(); - if (timestamp && this._dbusClient.indicator) - this._dbusClient.indicator.provideActivationToken(timestamp); - - this._dbusItem.handleEvent('clicked', GLib.Variant.new('i', 0), - timestamp); - }, - - _onPropertyChanged(dbusItem, prop, _value) { - if (prop === 'toggle-type' || prop === 'toggle-state') - MenuItemFactory._updateOrnament.call(this); - else if (prop === 'label') - MenuItemFactory._updateLabel.call(this); - else if (prop === 'enabled') - MenuItemFactory._updateSensitive.call(this); - else if (prop === 'visible') - MenuItemFactory._updateVisible.call(this); - else if (prop === 'icon-name' || prop === 'icon-data') - MenuItemFactory._updateImage.call(this); - else if (prop === 'type' || prop === 'children-display') - MenuItemFactory._replaceSelf.call(this); - else - Util.Logger.debug(`Unhandled property change: ${prop}`); - }, - - _onChildAdded(dbusItem, child, position) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to add a child to non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - this.menu.addMenuItem(MenuItemFactory.createItem(this._dbusClient, child), position); - } - }, - - _onChildRemoved(dbusItem, child) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to remove a child from non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - // find it! - this.menu._getMenuItems().forEach(item => { - if (item._dbusItem === child) - item.destroy(); - }); - } - }, - - _onChildMoved(dbusItem, child, oldpos, newpos) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to move a child in non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - MenuUtils.moveItemInMenu(this.menu, child, newpos); - } - }, - - _updateLabel() { - const label = this._dbusItem.propertyGet('label').replace(/_([^_])/, '$1'); - - if (this.label) // especially on GS3.8, the separator item might not even have a hidden label - this.label.set_text(label); - }, - - _updateOrnament() { - if (!this.setOrnament) - return; // separators and alike might not have gotten the polyfill - - if (this._dbusItem.propertyGet('toggle-type') === 'checkmark' && - this._dbusItem.propertyGetInt('toggle-state')) - this.setOrnament(PopupMenu.Ornament.CHECK); - else if (this._dbusItem.propertyGet('toggle-type') === 'radio' && - this._dbusItem.propertyGetInt('toggle-state')) - this.setOrnament(PopupMenu.Ornament.DOT); - else - this.setOrnament(PopupMenu.Ornament.NONE); - }, - - async _updateImage() { - if (!this._icon) - return; // might be missing on submenus / separators - - const iconName = this._dbusItem.propertyGet('icon-name'); - const iconData = this._dbusItem.propertyGetVariant('icon-data'); - if (iconName) { - this._icon.icon_name = iconName; - } else if (iconData) { - try { - const inputStream = Gio.MemoryInputStream.new_from_bytes( - iconData.get_data_as_bytes()); - this._icon.gicon = await GdkPixbuf.Pixbuf.new_from_stream_async( - inputStream, this._dbusClient.cancellable); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - }, - - _updateVisible() { - this.visible = this._dbusItem.propertyGetBool('visible'); - }, - - _updateSensitive() { - this.setSensitive(this._dbusItem.propertyGetBool('enabled')); - }, - - _replaceSelf(newSelf) { - // create our new self if needed - if (!newSelf) - newSelf = MenuItemFactory.createItem(this._dbusClient, this._dbusItem); - - // first, we need to find our old position - let pos = -1; - const family = this._parent._getMenuItems(); - for (let i = 0; i < family.length; ++i) { - if (family[i] === this) - pos = i; - } - - if (pos < 0) - throw new Error("DBusMenu: can't replace non existing menu item"); - - - // add our new self while we're still alive - this._parent.addMenuItem(newSelf, pos); - - // now destroy our old self - this.destroy(); - }, -}; - -/** - * Utility functions not necessarily belonging into the item factory - */ -const MenuUtils = { - moveItemInMenu(menu, dbusItem, newpos) { - // HACK: we're really getting into the internals of the PopupMenu implementation - - // First, find our wrapper. Children tend to lie. We do not trust the old positioning. - const family = menu._getMenuItems(); - for (let i = 0; i < family.length; ++i) { - if (family[i]._dbusItem === dbusItem) { - // now, remove it - menu.box.remove_child(family[i]); - - // and add it again somewhere else - if (newpos < family.length && family[newpos] !== family[i]) - menu.box.insert_child_below(family[i], family[newpos]); - else - menu.box.add(family[i]); - - // skip the rest - return; - } - } - }, -}; - - -/** - * Processes DBus events, creates the menu items and handles the actions - * - * Something like a mini-god-object - */ -export class Client extends Signals.EventEmitter { - constructor(busName, path, indicator) { - super(); - - this._busName = busName; - this._busPath = path; - this._client = new DBusClient(busName, path); - this._rootMenu = null; // the shell menu - this._rootItem = null; // the DbusMenuItem for the root - this.indicator = indicator; - this.cancellable = new Util.CancellableChild(this.indicator.cancellable); - - this._client.initAsync(this.cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - - Util.connectSmart(this._client, 'ready-changed', this, - () => this.emit('ready-changed')); - } - - get isReady() { - return this._client.isReady; - } - - // this will attach the client to an already existing menu that will be used as the root menu. - // it will also connect the client to be automatically destroyed when the menu dies. - attachToMenu(menu) { - this._rootMenu = menu; - this._rootItem = this._client.getRoot(); - this._itemsBeingAdded = new Set(); - - // cleanup: remove existing children (just in case) - this._rootMenu.removeAll(); - - if (NEED_NESTED_SUBMENU_FIX) - menu._setOpenedSubMenu = this._setOpenedSubmenu.bind(this); - - // connect handlers - Util.connectSmart(menu, 'open-state-changed', this, this._onMenuOpened); - Util.connectSmart(menu, 'destroy', this, this.destroy); - - Util.connectSmart(this._rootItem, 'child-added', this, this._onRootChildAdded); - Util.connectSmart(this._rootItem, 'child-removed', this, this._onRootChildRemoved); - Util.connectSmart(this._rootItem, 'child-moved', this, this._onRootChildMoved); - - // Dropbox requires us to call AboutToShow(0) first - this._rootItem.sendAboutToShow(); - - // fill the menu for the first time - const children = this._rootItem.getChildren(); - children.forEach(child => - this._onRootChildAdded(this._rootItem, child)); - } - - _setOpenedSubmenu(submenu) { - if (!submenu) - return; - - if (submenu._parent !== this._rootMenu) - return; - - if (submenu === this._openedSubMenu) - return; - - if (this._openedSubMenu && this._openedSubMenu.isOpen) - this._openedSubMenu.close(true); - - this._openedSubMenu = submenu; - } - - _onRootChildAdded(dbusItem, child, position) { - // Menu additions can be expensive, so let's do it in different chunks - const basePriority = this.isOpen ? GLib.PRIORITY_DEFAULT : GLib.PRIORITY_LOW; - const idlePromise = new PromiseUtils.IdlePromise( - basePriority + this._itemsBeingAdded.size, this.cancellable); - this._itemsBeingAdded.add(child); - - idlePromise.then(() => { - if (!this._itemsBeingAdded.has(child)) - return; - - this._rootMenu.addMenuItem( - MenuItemFactory.createItem(this, child), position); - }).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }).finally(() => this._itemsBeingAdded.delete(child)); - } - - _onRootChildRemoved(dbusItem, child) { - // children like to play hide and seek - // but we know how to find it for sure! - const item = this._rootMenu._getMenuItems().find(it => - it._dbusItem === child); - - if (item) - item.destroy(); - else - this._itemsBeingAdded.delete(child); - } - - _onRootChildMoved(dbusItem, child, oldpos, newpos) { - MenuUtils.moveItemInMenu(this._rootMenu, dbusItem, newpos); - } - - _onMenuOpened(menu, state) { - if (!this._rootItem) - return; - - this._client.active = state; - - if (state) { - if (this._openedSubMenu && this._openedSubMenu.isOpen) - this._openedSubMenu.close(); - - this._rootItem.handleEvent('opened', null, 0); - this._rootItem.sendAboutToShow(); - } else { - this._rootItem.handleEvent('closed', null, 0); - } - } - - destroy() { - this.emit('destroy'); - - if (this._client) - this._client.destroy(); - - this._client = null; - this._rootItem = null; - this._rootMenu = null; - this.indicator = null; - this._itemsBeingAdded = null; - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js deleted file mode 100644 index edf16fc..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js +++ /dev/null @@ -1,103 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import {CancellableChild, Logger} from './util.js'; - -Gio._promisify(Gio.DBusProxy.prototype, 'init_async'); - -export const DBusProxy = GObject.registerClass({ - Signals: {'destroy': {}}, -}, class DBusProxy extends Gio.DBusProxy { - static get TUPLE_VARIANT_TYPE() { - if (!this._tupleVariantType) - this._tupleVariantType = new GLib.VariantType('(v)'); - - return this._tupleVariantType; - } - - static destroy() { - delete this._tupleType; - } - - _init(busName, objectPath, interfaceInfo, flags = Gio.DBusProxyFlags.NONE) { - if (interfaceInfo.signals.length) - Logger.warn('Avoid exposing signals to gjs!'); - - super._init({ - gConnection: Gio.DBus.session, - gInterfaceName: interfaceInfo.name, - gInterfaceInfo: interfaceInfo, - gName: busName, - gObjectPath: objectPath, - gFlags: flags, - }); - - this._signalIds = []; - - if (!(flags & Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS)) { - this._signalIds.push(this.connect('g-signal', - (_proxy, ...args) => this._onSignal(...args))); - } - - this._signalIds.push(this.connect('notify::g-name-owner', () => - this._onNameOwnerChanged())); - } - - async initAsync(cancellable) { - cancellable = new CancellableChild(cancellable); - await this.init_async(GLib.PRIORITY_DEFAULT, cancellable); - this._cancellable = cancellable; - - this.gInterfaceInfo.methods.map(m => m.name).forEach(method => - this._ensureAsyncMethod(method)); - } - - destroy() { - this.emit('destroy'); - - this._signalIds.forEach(id => this.disconnect(id)); - - if (this._cancellable) - this._cancellable.cancel(); - } - - // This can be removed when we will have GNOME 43 as minimum version - _ensureAsyncMethod(method) { - if (this[`${method}Async`]) - return; - - if (!this[`${method}Remote`]) - throw new Error(`Missing remote method '${method}'`); - - this[`${method}Async`] = function (...args) { - return new Promise((resolve, reject) => { - this[`${method}Remote`](...args, (ret, e) => { - if (e) - reject(e); - else - resolve(ret); - }); - }); - }; - } - - _onSignal() { - } - - getProperty(propertyName, cancellable) { - return this.gConnection.call(this.gName, - this.gObjectPath, 'org.freedesktop.DBus.Properties', 'Get', - GLib.Variant.new('(ss)', [this.gInterfaceName, propertyName]), - DBusProxy.TUPLE_VARIANT_TYPE, Gio.DBusCallFlags.NONE, -1, - cancellable); - } - - getProperties(cancellable) { - return this.gConnection.call(this.gName, - this.gObjectPath, 'org.freedesktop.DBus.Properties', 'GetAll', - GLib.Variant.new('(s)', [this.gInterfaceName]), - GLib.VariantType.new('(a{sv})'), Gio.DBusCallFlags.NONE, -1, - cancellable); - } -}); diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js deleted file mode 100644 index 16e6596..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js +++ /dev/null @@ -1,89 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import * as Extension from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as StatusNotifierWatcher from './statusNotifierWatcher.js'; -import * as Interfaces from './interfaces.js'; -import * as TrayIconsManager from './trayIconsManager.js'; -import * as Util from './util.js'; -import {SettingsManager} from './settingsManager.js'; - -export default class DashToDockExtension extends Extension.Extension { - constructor(...args) { - super(...args); - - Util.Logger.init(this); - Interfaces.initialize(this); - - this._isEnabled = false; - this._statusNotifierWatcher = null; - this._watchDog = new Util.NameWatcher(StatusNotifierWatcher.WATCHER_BUS_NAME); - this._watchDog.connect('vanished', () => this._maybeEnableAfterNameAvailable()); - - // HACK: we want to leave the watchdog alive when disabling the extension, - // but if we are being reloaded, we destroy it since it could be considered - // a leak and spams our log, too. - /* eslint-disable no-undef */ - if (typeof global['--appindicator-extension-on-reload'] === 'function') - global['--appindicator-extension-on-reload'](); - - global['--appindicator-extension-on-reload'] = () => { - Util.Logger.debug('Reload detected, destroying old watchdog'); - this._watchDog.destroy(); - this._watchDog = null; - }; - /* eslint-enable no-undef */ - } - - enable() { - this._isEnabled = true; - SettingsManager.initialize(this); - Util.tryCleanupOldIndicators(); - this._maybeEnableAfterNameAvailable(); - TrayIconsManager.TrayIconsManager.initialize(); - } - - disable() { - this._isEnabled = false; - TrayIconsManager.TrayIconsManager.destroy(); - - if (this._statusNotifierWatcher !== null) { - this._statusNotifierWatcher.destroy(); - this._statusNotifierWatcher = null; - } - - SettingsManager.destroy(); - } - - // FIXME: when entering/leaving the lock screen, the extension might be - // enabled/disabled rapidly. - // This will create very bad side effects in case we were not done unowning - // the name while trying to own it again. Since g_bus_unown_name doesn't - // fire any callback when it's done, we need to monitor the bus manually - // to find out when the name vanished so we can reclaim it again. - _maybeEnableAfterNameAvailable() { - // by the time we get called whe might not be enabled - if (!this._isEnabled || this._statusNotifierWatcher) - return; - - if (this._watchDog.nameAcquired && this._watchDog.nameOnBus) - return; - - this._statusNotifierWatcher = new StatusNotifierWatcher.StatusNotifierWatcher( - this._watchDog); - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js deleted file mode 100644 index b775307..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js +++ /dev/null @@ -1,179 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; - -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; - -// The icon cache caches icon objects in case they're reused shortly aftwerwards. -// This is necessary for some indicators like skype which rapidly switch between serveral icons. -// Without caching, the garbage collection would never be able to handle the amount of new icon data. -// If the lifetime of an icon is over, the cache will destroy the icon. (!) -// The presence of active icons will extend the lifetime. - -const GC_INTERVAL = 100; // seconds -const LIFETIME_TIMESPAN = 120; // seconds - -// how to use: see IconCache.add, IconCache.get -export class IconCache { - constructor() { - this._cache = new Map(); - this._activeIcons = Object.create(null); - this._lifetime = new Map(); // we don't want to attach lifetime to the object - } - - add(id, icon) { - if (!(icon instanceof Gio.Icon)) { - Util.Logger.critical('IconCache: Only Gio.Icons are supported'); - return null; - } - - if (!id) { - Util.Logger.critical('IconCache: Invalid ID provided'); - return null; - } - - const oldIcon = this._cache.get(id); - if (!oldIcon || !oldIcon.equals(icon)) { - Util.Logger.debug(`IconCache: adding ${id}: ${icon}`); - this._cache.set(id, icon); - } else { - icon = oldIcon; - } - - this._renewLifetime(id); - this._checkGC(); - - return icon; - } - - updateActive(iconType, gicon, isActive) { - if (!gicon) - return; - - const previousActive = this._activeIcons[iconType]; - - if (isActive && [...this._cache.values()].some(icon => icon === gicon)) - this._activeIcons[iconType] = gicon; - else if (previousActive === gicon) - delete this._activeIcons[iconType]; - else - return; - - if (previousActive) { - this._cache.forEach((icon, id) => { - if (icon === previousActive) - this._renewLifetime(id); - }); - } - } - - _remove(id) { - Util.Logger.debug(`IconCache: removing ${id}`); - - this._cache.delete(id); - this._lifetime.delete(id); - } - - _renewLifetime(id) { - this._lifetime.set(id, new Date().getTime() + LIFETIME_TIMESPAN * 1000); - } - - forceDestroy(id) { - const gicon = this._cache.has(id); - if (gicon) { - Object.keys(this._activeIcons).forEach(iconType => - this.updateActive(iconType, gicon, false)); - this._remove(id); - this._checkGC(); - } - } - - // marks all the icons as removable, if something doesn't claim them before - weakClear() { - this._activeIcons = Object.create(null); - this._checkGC(); - } - - // removes everything from the cache - clear() { - this._activeIcons = Object.create(null); - this._cache.forEach((_icon, id) => this._remove(id)); - this._checkGC(); - } - - // returns an object from the cache, or null if it can't be found. - get(id) { - const icon = this._cache.get(id); - if (icon) { - Util.Logger.debug(`IconCache: retrieving ${id}: ${icon}`); - this._renewLifetime(id); - return icon; - } - - return null; - } - - async _checkGC() { - const cacheIsEmpty = this._cache.size === 0; - - if (!cacheIsEmpty && !this._gcTimeout) { - Util.Logger.debug('IconCache: garbage collector started'); - let anyUnusedInCache = false; - this._gcTimeout = new PromiseUtils.TimeoutSecondsPromise(GC_INTERVAL, - GLib.PRIORITY_LOW); - try { - await this._gcTimeout; - anyUnusedInCache = this._gc(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'IconCache: garbage collector'); - } finally { - delete this._gcTimeout; - } - - if (anyUnusedInCache) - this._checkGC(); - } else if (cacheIsEmpty && this._gcTimeout) { - Util.Logger.debug('IconCache: garbage collector stopped'); - this._gcTimeout.cancel(); - } - } - - _gc() { - const time = new Date().getTime(); - let anyUnused = false; - - this._cache.forEach((icon, id) => { - if (Object.values(this._activeIcons).includes(icon)) { - Util.Logger.debug(`IconCache: ${id} is in use.`); - } else if (this._lifetime.get(id) < time) { - this._remove(id); - } else { - anyUnused = true; - Util.Logger.debug(`IconCache: ${id} survived this round.`); - } - }); - - return anyUnused; - } - - destroy() { - this.clear(); - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js deleted file mode 100644 index 5ef516c..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js +++ /dev/null @@ -1,592 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Panel from 'resource:///org/gnome/shell/ui/panel.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; - -import * as AppIndicator from './appIndicator.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as SettingsManager from './settingsManager.js'; -import * as Util from './util.js'; -import * as DBusMenu from './dbusMenu.js'; - -const DEFAULT_ICON_SIZE = Panel.PANEL_ICON_SIZE || 16; - -export function addIconToPanel(statusIcon) { - if (!(statusIcon instanceof BaseStatusIcon)) - throw TypeError(`Unexpected icon type: ${statusIcon}`); - - const settings = SettingsManager.getDefaultGSettings(); - const indicatorId = `appindicator-${statusIcon.uniqueId}`; - - const currentIcon = Main.panel.statusArea[indicatorId]; - if (currentIcon) { - if (currentIcon !== statusIcon) - currentIcon.destroy(); - - Main.panel.statusArea[indicatorId] = null; - } - - Main.panel.addToStatusArea(indicatorId, statusIcon, 1, - settings.get_string('tray-pos')); - - Util.connectSmart(settings, 'changed::tray-pos', statusIcon, () => - addIconToPanel(statusIcon)); -} - -export function getTrayIcons() { - return Object.values(Main.panel.statusArea).filter( - i => i instanceof IndicatorStatusTrayIcon); -} - -export function getAppIndicatorIcons() { - return Object.values(Main.panel.statusArea).filter( - i => i instanceof IndicatorStatusIcon); -} - -export const BaseStatusIcon = GObject.registerClass( -class IndicatorBaseStatusIcon extends PanelMenu.Button { - _init(menuAlignment, nameText, iconActor, dontCreateMenu) { - super._init(menuAlignment, nameText, dontCreateMenu); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-opacity', this, this._updateOpacity); - this.connect('notify::hover', () => this._onHoverChanged()); - - if (!super._onDestroy) - this.connect('destroy', () => this._onDestroy()); - - this._box = new St.BoxLayout({style_class: 'panel-status-indicators-box'}); - this.add_child(this._box); - - this._setIconActor(iconActor); - this._showIfReady(); - } - - _setIconActor(icon) { - if (!(icon instanceof Clutter.Actor)) - throw new Error(`${icon} is not a valid actor`); - - if (this._icon && this._icon !== icon) - this._icon.destroy(); - - this._icon = icon; - this._updateEffects(); - this._monitorIconEffects(); - - if (this._icon) { - this._box.add_child(this._icon); - const id = this._icon.connect('destroy', () => { - this._icon.disconnect(id); - this._icon = null; - this._monitorIconEffects(); - }); - } - } - - _onDestroy() { - if (this._icon) - this._icon.destroy(); - - if (super._onDestroy) - super._onDestroy(); - } - - isReady() { - throw new GObject.NotImplementedError('isReady() in %s'.format(this.constructor.name)); - } - - get icon() { - return this._icon; - } - - get uniqueId() { - throw new GObject.NotImplementedError('uniqueId in %s'.format(this.constructor.name)); - } - - _showIfReady() { - this.visible = this.isReady(); - } - - _onHoverChanged() { - if (this.hover) { - this.opacity = 255; - if (this._icon) - this._icon.remove_effect_by_name('desaturate'); - } else { - this._updateEffects(); - } - } - - _updateOpacity() { - const settings = SettingsManager.getDefaultGSettings(); - const userValue = settings.get_user_value('icon-opacity'); - if (userValue) - this.opacity = userValue.unpack(); - else - this.opacity = 255; - } - - _updateEffects() { - this._updateOpacity(); - - if (this._icon) { - this._updateSaturation(); - this._updateBrightnessContrast(); - } - } - - _monitorIconEffects() { - const settings = SettingsManager.getDefaultGSettings(); - const monitoring = !!this._iconSaturationIds; - - if (!this._icon && monitoring) { - Util.disconnectSmart(settings, this, this._iconSaturationIds); - delete this._iconSaturationIds; - - Util.disconnectSmart(settings, this, this._iconBrightnessIds); - delete this._iconBrightnessIds; - - Util.disconnectSmart(settings, this, this._iconContrastIds); - delete this._iconContrastIds; - } else if (this._icon && !monitoring) { - this._iconSaturationIds = - Util.connectSmart(settings, 'changed::icon-saturation', this, - this._updateSaturation); - this._iconBrightnessIds = - Util.connectSmart(settings, 'changed::icon-brightness', this, - this._updateBrightnessContrast); - this._iconContrastIds = - Util.connectSmart(settings, 'changed::icon-contrast', this, - this._updateBrightnessContrast); - } - } - - _updateSaturation() { - const settings = SettingsManager.getDefaultGSettings(); - const desaturationValue = settings.get_double('icon-saturation'); - let desaturateEffect = this._icon.get_effect('desaturate'); - - if (desaturationValue > 0) { - if (!desaturateEffect) { - desaturateEffect = new Clutter.DesaturateEffect(); - this._icon.add_effect_with_name('desaturate', desaturateEffect); - } - desaturateEffect.set_factor(desaturationValue); - } else if (desaturateEffect) { - this._icon.remove_effect(desaturateEffect); - } - } - - _updateBrightnessContrast() { - const settings = SettingsManager.getDefaultGSettings(); - const brightnessValue = settings.get_double('icon-brightness'); - const contrastValue = settings.get_double('icon-contrast'); - let brightnessContrastEffect = this._icon.get_effect('brightness-contrast'); - - if (brightnessValue !== 0 | contrastValue !== 0) { - if (!brightnessContrastEffect) { - brightnessContrastEffect = new Clutter.BrightnessContrastEffect(); - this._icon.add_effect_with_name('brightness-contrast', brightnessContrastEffect); - } - brightnessContrastEffect.set_brightness(brightnessValue); - brightnessContrastEffect.set_contrast(contrastValue); - } else if (brightnessContrastEffect) { - this._icon.remove_effect(brightnessContrastEffect); - } - } -}); - -/* - * IndicatorStatusIcon implements an icon in the system status area - */ -export const IndicatorStatusIcon = GObject.registerClass( -class IndicatorStatusIcon extends BaseStatusIcon { - _init(indicator) { - super._init(0.5, indicator.accessibleName, - new AppIndicator.IconActor(indicator, DEFAULT_ICON_SIZE)); - this._indicator = indicator; - - this._lastClickTime = -1; - this._lastClickX = -1; - this._lastClickY = -1; - - this._box.add_style_class_name('appindicator-box'); - - Util.connectSmart(this._indicator, 'ready', this, this._showIfReady); - Util.connectSmart(this._indicator, 'menu', this, this._updateMenu); - Util.connectSmart(this._indicator, 'label', this, this._updateLabel); - Util.connectSmart(this._indicator, 'status', this, this._updateStatus); - Util.connectSmart(this._indicator, 'reset', this, () => { - this._updateStatus(); - this._updateLabel(); - }); - Util.connectSmart(this._indicator, 'accessible-name', this, () => - this.set_accessible_name(this._indicator.accessibleName)); - Util.connectSmart(this._indicator, 'destroy', this, () => this.destroy()); - - this.connect('notify::visible', () => this._updateMenu()); - - this._showIfReady(); - } - - _onDestroy() { - if (this._menuClient) { - this._menuClient.disconnect(this._menuReadyId); - this._menuClient.destroy(); - this._menuClient = null; - } - - super._onDestroy(); - } - - get uniqueId() { - return this._indicator.uniqueId; - } - - isReady() { - return this._indicator && this._indicator.isReady; - } - - _updateLabel() { - const {label} = this._indicator; - if (label) { - if (!this._label || !this._labelBin) { - this._labelBin = new St.Bin({ - yAlign: Clutter.ActorAlign.CENTER, - }); - this._label = new St.Label(); - this._labelBin.add_actor(this._label); - this._box.add_actor(this._labelBin); - } - this._label.set_text(label); - if (!this._box.contains(this._labelBin)) - this._box.add_actor(this._labelBin); // FIXME: why is it suddenly necessary? - } else if (this._label) { - this._labelBin.destroy_all_children(); - this._box.remove_actor(this._labelBin); - this._labelBin.destroy(); - delete this._labelBin; - delete this._label; - } - } - - _updateStatus() { - const wasVisible = this.visible; - this.visible = this._indicator.status !== AppIndicator.SNIStatus.PASSIVE; - - if (this.visible !== wasVisible) - this._indicator.checkAlive().catch(logError); - } - - _updateMenu() { - if (this._menuClient) { - this._menuClient.disconnect(this._menuReadyId); - this._menuClient.destroy(); - this._menuClient = null; - this.menu.removeAll(); - } - - if (this.visible && this._indicator.menuPath) { - this._menuClient = new DBusMenu.Client(this._indicator.busName, - this._indicator.menuPath, this._indicator); - - if (this._menuClient.isReady) - this._menuClient.attachToMenu(this.menu); - - this._menuReadyId = this._menuClient.connect('ready-changed', () => { - if (this._menuClient.isReady) - this._menuClient.attachToMenu(this.menu); - else - this._updateMenu(); - }); - } - } - - _showIfReady() { - if (!this.isReady()) - return; - - this._updateLabel(); - this._updateStatus(); - this._updateMenu(); - } - - _updateClickCount(event) { - const [x, y] = event.get_coords(); - const time = event.get_time(); - const {doubleClickDistance, doubleClickTime} = - Clutter.Settings.get_default(); - - if (time > (this._lastClickTime + doubleClickTime) || - (Math.abs(x - this._lastClickX) > doubleClickDistance) || - (Math.abs(y - this._lastClickY) > doubleClickDistance)) - this._clickCount = 0; - - this._lastClickTime = time; - this._lastClickX = x; - this._lastClickY = y; - - this._clickCount = (this._clickCount % 2) + 1; - - return this._clickCount; - } - - _maybeHandleDoubleClick(event) { - if (this._indicator.supportsActivation === false) - return Clutter.EVENT_PROPAGATE; - - if (event.get_button() !== Clutter.BUTTON_PRIMARY) - return Clutter.EVENT_PROPAGATE; - - if (this._updateClickCount(event) === 2) { - this._indicator.open(...event.get_coords(), event.get_time()); - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } - - async _waitForDoubleClick() { - const {doubleClickTime} = Clutter.Settings.get_default(); - this._waitDoubleClickPromise = new PromiseUtils.TimeoutPromise( - doubleClickTime); - - try { - await this._waitDoubleClickPromise; - this.menu.toggle(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - delete this._waitDoubleClickPromise; - } - } - - vfunc_event(event) { - if (this.menu.numMenuItems && event.type() === Clutter.EventType.TOUCH_BEGIN) - this.menu.toggle(); - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_button_press_event(event) { - if (this._waitDoubleClickPromise) - this._waitDoubleClickPromise.cancel(); - - // if middle mouse button clicked send SecondaryActivate dbus event and do not show appindicator menu - if (event.get_button() === Clutter.BUTTON_MIDDLE) { - if (Main.panel.menuManager.activeMenu) - Main.panel.menuManager._closeMenu(true, Main.panel.menuManager.activeMenu); - this._indicator.secondaryActivate(event.get_time(), ...event.get_coords()); - return Clutter.EVENT_STOP; - } - - if (event.get_button() === Clutter.BUTTON_SECONDARY) { - this.menu.toggle(); - return Clutter.EVENT_PROPAGATE; - } - - const doubleClickHandled = this._maybeHandleDoubleClick(event); - if (doubleClickHandled === Clutter.EVENT_PROPAGATE && - event.get_button() === Clutter.BUTTON_PRIMARY && - this.menu.numMenuItems) { - if (this._indicator.supportsActivation !== false) - this._waitForDoubleClick().catch(logError); - else - this.menu.toggle(); - } - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_button_release_event(event) { - if (!this._indicator.supportsActivation) - return this._maybeHandleDoubleClick(event); - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_scroll_event(event) { - // Since Clutter 1.10, clutter will always send a smooth scrolling event - // with explicit deltas, no matter what input device is used - // In fact, for every scroll there will be a smooth and non-smooth scroll - // event, and we can choose which one we interpret. - if (event.get_scroll_direction() === Clutter.ScrollDirection.SMOOTH) { - const [dx, dy] = event.get_scroll_delta(); - - this._indicator.scroll(dx, dy); - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } -}); - -export const IndicatorStatusTrayIcon = GObject.registerClass( -class IndicatorTrayIcon extends BaseStatusIcon { - _init(icon) { - super._init(0.5, icon.wm_class, icon, {dontCreateMenu: true}); - Util.Logger.debug(`Adding legacy tray icon ${this.uniqueId}`); - this._box.add_style_class_name('appindicator-trayicons-box'); - this.add_style_class_name('appindicator-icon'); - this.add_style_class_name('tray-icon'); - - this.connect('button-press-event', (_actor, _event) => { - this.add_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('button-release-event', (_actor, event) => { - this._icon.click(event); - this.remove_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('key-press-event', (_actor, event) => { - this.add_style_pseudo_class('active'); - this._icon.click(event); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('key-release-event', (_actor, event) => { - this._icon.click(event); - this.remove_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - - Util.connectSmart(this._icon, 'destroy', this, () => { - icon.clear_effects(); - this.destroy(); - }); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-size', this, this._updateIconSize); - - const themeContext = St.ThemeContext.get_for_stage(global.stage); - Util.connectSmart(themeContext, 'notify::scale-factor', this, () => - this._updateIconSize()); - - this._updateIconSize(); - } - - _onDestroy() { - Util.Logger.debug(`Destroying legacy tray icon ${this.uniqueId}`); - - if (this._waitDoubleClickPromise) - this._waitDoubleClickPromise.cancel(); - - super._onDestroy(); - } - - isReady() { - return !!this._icon; - } - - get uniqueId() { - return `legacy:${this._icon.wm_class}:${this._icon.pid}`; - } - - vfunc_navigate_focus(from, direction) { - this.grab_key_focus(); - return super.vfunc_navigate_focus(from, direction); - } - - _getSimulatedButtonEvent(touchEvent) { - const event = Clutter.Event.new(Clutter.EventType.BUTTON_RELEASE); - event.set_button(1); - event.set_time(touchEvent.get_time()); - event.set_flags(touchEvent.get_flags()); - event.set_stage(global.stage); - event.set_source(touchEvent.get_source()); - event.set_coords(...touchEvent.get_coords()); - event.set_state(touchEvent.get_state()); - return event; - } - - vfunc_touch_event(event) { - // Under X11 we rely on emulated pointer events - if (!imports.gi.Meta.is_wayland_compositor()) - return Clutter.EVENT_PROPAGATE; - - const slot = event.get_event_sequence().get_slot(); - - if (!this._touchPressSlot && - event.get_type() === Clutter.EventType.TOUCH_BEGIN) { - this.add_style_pseudo_class('active'); - this._touchButtonEvent = this._getSimulatedButtonEvent(event); - this._touchPressSlot = slot; - this._touchDelayPromise = new PromiseUtils.TimeoutPromise( - AppDisplay.MENU_POPUP_TIMEOUT); - this._touchDelayPromise.then(() => { - delete this._touchDelayPromise; - delete this._touchPressSlot; - this._touchButtonEvent.set_button(3); - this._icon.click(this._touchButtonEvent); - this.remove_style_pseudo_class('active'); - }); - } else if (event.get_type() === Clutter.EventType.TOUCH_END && - this._touchPressSlot === slot) { - delete this._touchPressSlot; - delete this._touchButtonEvent; - if (this._touchDelayPromise) { - this._touchDelayPromise.cancel(); - delete this._touchDelayPromise; - } - - this._icon.click(this._getSimulatedButtonEvent(event)); - this.remove_style_pseudo_class('active'); - } else if (event.get_type() === Clutter.EventType.TOUCH_UPDATE && - this._touchPressSlot === slot) { - this.add_style_pseudo_class('active'); - this._touchButtonEvent = this._getSimulatedButtonEvent(event); - } - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_leave_event(event) { - this.remove_style_pseudo_class('active'); - - if (this._touchDelayPromise) { - this._touchDelayPromise.cancel(); - delete this._touchDelayPromise; - } - - return super.vfunc_leave_event(event); - } - - _updateIconSize() { - const settings = SettingsManager.getDefaultGSettings(); - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - let iconSize = settings.get_int('icon-size'); - - if (iconSize <= 0) - iconSize = DEFAULT_ICON_SIZE; - - this.height = -1; - this._icon.set({ - width: iconSize * scaleFactor, - height: iconSize * scaleFactor, - xAlign: Clutter.ActorAlign.CENTER, - yAlign: Clutter.ActorAlign.CENTER, - }); - } -}); diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml deleted file mode 100644 index e98e04e..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml deleted file mode 100644 index 8c36294..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml deleted file mode 100644 index e450d04..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js deleted file mode 100644 index 0a97907..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js +++ /dev/null @@ -1,52 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -export let StatusNotifierItem = null; -export let StatusNotifierWatcher = null; -export let DBusMenu = null; - -// loads a xml file into an in-memory string -function loadInterfaceXml(extension, filename) { - const interfacesDir = extension.dir.get_child('interfaces-xml'); - const file = interfacesDir.get_child(filename); - const [result, contents] = imports.gi.GLib.file_get_contents(file.get_path()); - - if (result) { - // HACK: The "" + trick is important as hell because file_get_contents returns - // an object (WTF?) but Gio.makeProxyWrapper requires `typeof() === "string"` - // Otherwise, it will try to check `instanceof XML` and fail miserably because there - // is no `XML` on very recent SpiderMonkey releases (or, if SpiderMonkey is old enough, - // will spit out a TypeError soon). - let nodeContents = contents; - if (contents instanceof Uint8Array) - nodeContents = imports.byteArray.toString(contents); - return `${nodeContents}`; - } else { - throw new Error(`AppIndicatorSupport: Could not load file: ${filename}`); - } -} - -export function initialize(extension) { - StatusNotifierItem = loadInterfaceXml(extension, 'StatusNotifierItem.xml'); - StatusNotifierWatcher = loadInterfaceXml(extension, 'StatusNotifierWatcher.xml'); - DBusMenu = loadInterfaceXml(extension, 'DBusMenu.xml'); -} - -export function destroy() { - StatusNotifierItem = null; - StatusNotifierWatcher = null; - DBusMenu = null; -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index c66d72ef88af4d23c37db2b16f784624bb96bd87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2225 zcma)+%Wqpn6o&^|9yJtbdA7U`n<^2#spGVzb>kM=G*!|zvC`CH$>e%s550HBni)H_ zg#=>F0)#-SxBB-i3w{O`z^_39zXu-$e+3^0e*<3w{{Wu^#jXMOf^R@P z2<`!=bIyVmQL;2rQiOo#=Lzb}ETpMad_8pwHm1U?0RmGfKh zb;v)0oX79^{-62&Um)8%fFxc3r$DaDJcyEs1mt)vh@+wn^7#)yuK$-H>wN=qJU@ZQ z!Jk1szYD=J3*Zd651a;TAouoj5NV2+Fki%EpKOnN!1a3?a~~!T?i2fjig*qaF0$I9 zM44|Os};w`gZ(~_$$cCSt_=_N&3SQ6M+f(g`#3tXd-F~R$^>l<&Bgdxkf{=9oo+OP zQQnU%X)M*IOwr^-@i3+GdYP~q7w4d@oH%DqaMFj(#ZJfDKG-z#<;A&ypyAky8RcbY zJDJ5Y@KxOIYAe8O<#kVq%~kGi7~9F?<0Id+p_aa`l6K`gRb=nnaS!_u*1<6_a(l_NI8CaTu!ESt>@r&g6yCRSc7sa7Im zMbdOBD?k<3jrg<@z*>KZ3-9wvYLNd_}lcMvY>g@X}4$)jaswwAjkIGa)Zq|k9 zvTx{mbhh2_(Xz#Mbun5}9nFWL85vZWO2twsDjtoBC#hI0Pac1>SSl6^mvE0FxHLZD z29#+=8m$sqYI}8!rc7*TWHXLz`0+H>L9`RIV=1Mklt;aWH6Ibl$|aj=NK)6Dv9tstGP^ z63tqd`ZAeTCi=?MDH<#*V`HXLnH;AxRHQPEnbVaL9Xdp2x^k2^C$U)?KUH`)x}c20 z-REqpR@HT&sfpsmWI-(S*L$i%`kKW>@zieFo^|H#P1C=fih1dI?(o)XihS6(q3UgM zariuki=9*w)E=e>{zPrNxL9A2uA}(-zdq2>SVc`G2-=6CsZnvLp8t{XW8Hq7I)ewR z;-*-#J>^5Y)umMRbY@PbdWUT?k`leK9`4>0c(}Dhb*#APx}kqN#{<5zcU!d^H)I`Y zjc8v@`?o#JaJD1cRW4}9CM#XBAe&Bds}j9pv1R(V@;-I)x}}@pQjby_bZ6r`QENGg zpssWSsskfF$WBm)=~`V4GQ_szCO|t&1=*6vxBhxAXI`jhSDftGj(pGvq8+^5yb%AP VT(foSY=@)o$!xLCIcLgU@efOqPPza9 diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 6edb41980de1d45d7c86ce38d2c0802fcab21cc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 949 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 diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index d22309b6758db3bc2bcafd3abb98362948c6a804..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 972 zcmZ{i%}>-o7{*7%uO?ndOhkzpFDlVlyK4|AVhmpf17U-!A>PLBP=@qlGaU$v7t_6% zsNhB8K`(}2Nc=buWhL;hcc&PuAH7G)^XBF2n@S7>-zja1ztb}qw zY%e!A>ABWHM#YpS<0WoOUEZ^t>+I|x6NyJsP`pg110@&Wg}aoy((ygmBY73f2wSs} zBD*J42oDxDCPXPvnvI2yEVBMtCuD^HkMrYfLd?k|i4AfsESfX3UCiuZ*)E#PS=pXT zX3jK?Q5=?GOFwkE4iw%T<-Rk^9l;8MdltPdJ+Dmf*eIkWy*`tKnXnPwbUZHIj2(D4 z{=R0>8E%Y?j1BF0#0NH#4~sLfLb(JlTFmP!C6`OTm)g@@g+lk;Eex~noxH@-lu&HQ zw}Ybe9gB89klL7Jw}db72NJLOKoq5>xr~{)YUEw~7?%wP$_p*(m(noo%l6X7w9o7{ z$oE%^^^KMNTcB3`P+$H?;%F_d;CdWaR^#X^Ci|z?w^mWAwzXKRK51m^X@xj?8%N8{ za?$5>zR}Fw)fM&i6;i7{`|)ULx4G@+OdF%Vv_?`x@8im5TzL~m)i_#@EAL>G`~jg$ B7a{-v diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 6d33af8d4f006780fdcf914f604e6d9ed568b8de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2373 zcma)+-)~e!6vszJg;o54zY)#R#DprhY!@o9P?g_SK^iE=7+$Ws)7`6k@7>&cD=mqk z)-9<}LkUzDvo$pqv7`@+R$OB1i}A@9ee;Qg7a#V{{s|_2&-Ct(q7WvT{mhv=Gv|BG znb~WrmQ4t>XVBN6FS|pCHc)}w#_ts35%3Hc122FCmce_#Kf&eTU*NOgb?|;r+_lJ+ z;BzongDb#o5%+*k!|nlBfjN-(9S2#*SY*$D%V1vt?*)GbSA)NTE5U2vL!bih1OEZn zgDbGb>mbKvU=f$}Np!YRCh<5r*Fft9A4ccK=V@Qyqv&w0bBh$| zTmo7X$HR^NK8DV9thWcE0pBaG1In_baSWWl)~4^x_8^c>V7U%;r||QZX-l!gvohJh zk-pzDq_wu?B+2M#kFO)!97qyIZDJ>OOHb@{oxn5wpfR}F@_s*XZSBh!I~NTLj(xF9 z`exAYnOe)DulQ0|O@VskTgRkmj3R$^ZChS$Yx!n5l(zfR;x$-Y1w;BCQRoi{j4bau9h172Es#K-UvJ+5!*Xc`lq?312! zQqmU(Wj<%7B$>`2=>%v6lxj%{^?67Y6xqC zPb7@^MkA4+j!nspoiD|=#N)AjxLgKwIDU?+k|Z@br=})qle4rfZA!a8w<+;j#x|{7 zd&;$6!FngtZ)T*?D^2^hS10KMH@3ff|L$fqxaBdv-H6uc9n3>uAP0i=sGj9)rBv4R zd>M2d?%iW-ZmwgUD7CTMNx5mcm+6 zslp1!hN9Q1rq8H}^8yp$Rcz3>^@ibD_2rEEYMj)?A>_O1T&P=ox?F%Ds+Pwgqwa?*V?USK!7;)+xEIq5Sl+9 diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 9d81088f9018447ac7bc68c2d1d3838ade4b8182..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmaiy&2AGh6on0xzd>xeD;fDk(~b2D)>V@I}AHQ^oD z!HSn)0~?-%1rl!nZ@`&0B`TuA($O~_U;7^W-tV(B?-@n_-Gg%IHuM!L$4`huzo2W- z>?OwTgLB|KSO@QdufZAc2)qNn1+Ri1z&Y?EcnE!lIOg+L7`p|of#rG6!18|qJ^<7CGsMR(fUhBqTh4&Q5|Ar^a-)JW0}6s<2(^dbU51 ziSnbrmTQZP6?Ra1WF0F&Q1>bT&nO8duuwk`)^| zF{#p7%t^gJ46YVE9#PkV^4?AZ37{vqy0&Jz_!vafVXIc%`s7E=iE diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index fe31bca0df8328b560949fb09eab0882752c4161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2334 zcmb7^J8T?97{>=Nj~pa`Aw0rE9|DP3WSz5}Kyt=_=;lrijG<+k4s&2}auc&CJbw?{BV+k9{sM zp1}7wzOh?`m;kSXJU+QqhzGz=!3y{dNZ|M29pJCvUEo#lN$@xD9#GuYpgG`>&xJs;1%!~Sb&GYYv6t0b?|QR26z%YgiE)B zXF<06W$*>?Rd5FU5PTH84A$Z6FCg206i%_6Q{dC!D;CmP!(p1Xj9B};D=KJySU^_VHxKiqb$}%Ph zQKK8X?<3f;*|zJ4myPNyfTu5@cR9ZTgN1eb9)4HhyF_oe5^9Fs)6UdagQM ztyWf0TmkGbF6OM%=(U{d)=+bPx%g-U|C@F$+bU=&nLuuTU86LttTt8`hxVavD_pO* zAGEeJsPt;fpF}>inWeBJty6yP_102wW_XS@BYDB13DXGGQ=>C)YhP)`DA_nzN^Rn5 zWU_MU=B8(-)wv{Rgv~IGg+OSs)+MQbEGK#{ev%cSo~-t zMVKNOCPY}oN{-IsT9STrUKSvYbR_13mb7Zni6b*Q*p>Y&jZ&?n3^_~<(z_!g>Cho; z%|EvLt;*K*t?2h^Ut-^ZEV>JMv1_gDbvq*8ZGY(p4wtVW zY%Dv!_{>IV#e+im2`HnKsd%8NSv~{B9u*yrx$?pq?}V{JO!Oby=>crb{}-{jeNXaE2J diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 4536d6e544d3ce1aa88f91a8c2a42b75b2787d36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2451 zcma)+O>7%Q6vrn}ptyXt1qyB9acI?uZfZL%q)t=%l~!q*#A;HCDkL;rPwlb2Gpn63 zj;(U3D7|vw5LH6rL=PN*Ub$gQ91!Bbxe|y27mzr?k^ft-ous7_Bd>omvor7g-+MEA zZ~K-{1=?$P_Tbq$Cd4@S)Fb#q`wH9vehucpK1kqC;N#$5;8yS-@Ktc^QS1dNV*tL6 zaS0^wy^J4%Ph$L8#yj9{jK2Z5gFk|7=NFK5{h5uoZ4m-Lu?v4sfP2ALz5}X8o178MrVbL0LPz0aH_y+{ZI`4s;qu)W^zZK3o z?j0bBGgt5x_amFt|*7ZHedVdCa|F0nXAA?bz-wo~s$3di4oCEO_=kdpR zUj}*o6_E4h!I!{KK-PB$JPO_gS^pmy{|2Wp9>XNF1ae#sMA&IA*)IFsg@?6rJvbM9 z4!E(s7x2K8co7ezr<#$%)HjgE#Jae#Ue?C>;l^=sjkvLIt_#YWHm*6hXYp{|H@0VZ zaMF8aytansLi{btNQqO4uGYL!&TZ(@fk>MY1%-+HL5k#RiO?Gtr?Fcl;zVe%0%^G>Nspx{L%CJK#iR=vQkZZ-UO}xk! zGzSZyr$edj(Sr35)1K2^B}TnW@i4lhZ;o$xrwzq=RW-AzScckEHw~z*eGSWeO%b~m zbEcw0>1{%DXT$|{&5I@8<~u{)=dgI>$hcTaDk>p1!zRks=`;}Qc{+!HQRQI4Rdppe)vCH+#g-^nUJ5R%4>T_c&PcCHRLmDAgZ$y3Sfpa1l%IMd zU(Dxo7jQfS=rFFyRVmQ|s-fyMFOygs*U)sV!QvYJL}NHL;Z;~Wj;*HJl2sL~C>g=! za9pCenOm4!m|d5SOOfNtfY5@KP7F0(t@=YKl{V89)@0(8pSiShHkevp$D&ZzVAh1T zf`e6}sjJ%O%1zvdW^mRfkt>mj)1jN0oQ7L|GjqVq%oONt$`fAiE98&Q6lwqdw0msk zFn15|bpBYONY}5Y^ZDb2!{gXez?S0pbne~YoH7d6jx$oWs-itjP822zIk70aZAltQ z=}@aJt6H3w&e;C#-mUfC!|plaheD&3m>+%`hMk9OS=7pTX(}?Q*tQz@75_Oo{8WT> zIlM!gzZ94IH+nb2E-hVk{Tr=nZ;h5c65s8FHJU>_Vz|JL7Ql73fCJtbySQk(k;Y9( zGqGtj^qzeX`IE6}F}3m4XgGy?S`$kZ=X+~0E-O3OG$JD@mafsFuB^!ZM*?4rvZbbK ztGbv^Iyk2p?(>*_Gv;km)dzKXz);yDXr$?W2bU0UTPvfbxPp7pyBQO*Zkr}cJfU*y z)#yYzRV~3TMb>xP-`#Dq#5j?xaZ$QX2y05DhAFoF8@B%~&ybfP?pAkXAkw|HN*8G` zhVAle*d1&*I*qod$-78)1UwkgmSslzn$1h!?xwRJJ)euML0)w@h^KP BjOqXY diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 0bb1b446dc2ad303fb7e7d62bf7df7174a78aa80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1067 zcmZ{iPfrvv7{&+1KTP6<8){5BXxPN!?5-#bLUdUmBoH>6(HJkL>~v>KI_=nY3E)@I zqn^AN51zPq@Z@bjg%=Ng0{sR)okbQ2HhJ>vOy9om+xGb}IsPud2%(#hgswr~AU}RV z1o{nKh9<{?;1)OqPJ{E{4e$jx4(@^1!Pnp=@I5#MegNM>Um?H0d2yJp15V?67rYI= z0q=lcz^mYQ(8vD-uYhAH;^QYkq$+FrIu{^6e9Q!d@N)PZe)!(~8H0uqS1iVl(F>D=Ns*}>?FB8PcX`Lrjg&s)#-fLq zB)ae=Ep5rZ4colX#?dXCiIg__nWc%2N!Z$^ZN4Y`4%%dn$D|fj7ie^!Rv(gDJ&tNL zsz*_{iIY>*S5`8oO-$OX%eW+K=!7dSB`1$e`K#M~oGG32S#7dq>{D5vWt=9QMr;~g`TaD5sEN2SkQcea(cyR8GTqg83F5|q#R_&`kHz^z1EM*8k8&+DaDGV2m X1y7_78Vc+qzQ!viuzzehTX&N$XqrvQ)vk# zr3BQJ*hFI_8bxAEd@!-pZd-eO!WW4-^ABh=>Z6H?4?g<+oxOCou?7;I?#$<$nR9;E z?@WJKv*LY$<5`?f<6OH;h-UDCyKuoV0zLxX02AO%kU$0A1O5Tt2mS><11?*Ry&zR+ zfEzGRg9N@-;d$_W%s;8{3-Bq-N5M7V_aNK(3FNqbugq7j5CT834wrku_284>M({y! z54Z|E46X!EfLp=S;N9RyAm?!%+y;ILwt~NaPk`&N=qhTE0-G@Z4oN-){s}$@E{D_A zU=zrG)1V0+2MzFYg<}=|3?9S%RVWfO2XZ|pLH2hGd>;G_~d64(r0?&iLf)XWbhY2JPCAkf$-I^A zr=Gy-FWaH8w^;OpNK_U$ruNA$WtRzGm~E6yrOj=d%~sP)9D))Jxb#AY8<3`#9C1`8<2?tA_JwsE7rJQd_p*KtGD=hXNjpk(J5ax49Pk4-Op{mC(=gMzgUZ89 zleaNxW->|Iw263VZpb8)w3|%Aa?E#SQq@O0GcWK^?=W{JO*(h3yaj8_X6#8~PpWxG z;#K3I^d#Oou2Q!zb9O|nEv+r7gis%-5jCSqYBnCmbw-dJ^w>kKQC@Z1ho7Ir# zyYM(2zk^aua&<_}!`T@AN=S5EO~n@}zNqsZ!Htp{jo-q`OZ5>V1;S64rld+j{U0{3 z{zG3sg#ad40`Wk7Jm`4ClSytq7eY-{i%>2Be?pgD%2~~$8&l{CcV{@hB-B-wfUXVN zrlv^?a9oX{Om#hDU7~Myu(+{+*oY2r+$@bbq=!$mx~`_V0j%h2=*66xz?DT_r^F>5 zH0G_p-&2RUg23+o?nikx_7ZEBWOz9h=&$wnGowp zS!1^=e}1JWATES5!!?-Ku5}fbP`Xf`l?AJNK3a}w3#qSJ)w=U2q)v_a-AA4`w9Rp@ zHot`UfK+)^t~3+1=YW*x^>R^&Z(+? zxNXz70_|<|x6n5|A;dWN2;}zllR~@#ego#fn;?Ndg3o}zg3p4#f$xBSfX{>CsXn)Y z?_s(F+yWjOa0=Xsc?H}CHbJ)g3}hYG2lHFtCd}`Eo56eF4zLGq1s{ShfserFz`w!0 z;1(D?4ITkm_X+S2coy6Teh$6~-T_nO`U}WGYD8PZsyO^Kqyp8Re~k`Sy$1Vk_qfCOkX&?8WLAA$5#-NqPb2AFF`GZy(qCZN2%73&Z|(q zJU0~`Uft)U@i>p@w5iz`7otRm=XJ<^6rE8<;UZdBqKZ|q4zv&c&*OSWsD$y&{hgPTKN z>*hlTgZ~wNyN?-AyZ?Y~ts!P@*N0Zxp+v=9ojH_=-e8%Gq^5pwBjB%MQdC!#W!s8# zt`juskm0f5**mUSCu1bGYJ54-3dP9MU0to9o^89bJl_!)WrJ;y;mUGr-ty|Gbky#b z?tU_oOI=EA=-qDHwy36#RbA@c4_qR+@W=B+J diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index a7770c5993c41ecfb767e84d1c9bc8f8e6867140..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1132 zcmaiyO=}ZD7{^DgZ;M`ftBOn!OM{toH+@UDU4_0$p{1cl5l@cEG+o*3hTUmtYY#~e zdK3gjswf`37irqkm-rQCzkr`X@#?|18^Pge9w6?q?7zT6&@}P^* z9;C-th(h0>Gf?XZLau^sU^|!rFM|)j7H|Q)1U>;zgRj6g@Ga;;n@|_xYo`dg0Nw#p z;6sps&%s`BA3O(s2X+1rPv}RAy2Ux^ zizuR_qOe zINCmJGSHVGlVVnq=`zo|a_NulbZ>8h%xI4!7xE=K7liIIyl{_l&n@~T*dy66cr5ag zO%&KY5k~M}Q)5PygHW=msOT2h@O&|1xd6-AX*MGkT%E*5xfC`{n^r$F2bk4It!_J= zxnZVF)0o6%8Cv?0$7K+ra+3SSd0rGOCwS?%*rrivOifIU9XH3z8T!Rwj^&ohXd=a; z>?(WQ^#^Hwj)#$u&fVNN%N*zFUb7-(V}3p;xPH;5nMbZP?z7v%7kFB2A{&T;D``4q zrn-%+hZpzQco3E%oBHKO7&+a8^kC|A`qwSfaV*-=LG{#ZcPxwEq9#Q;;+szTXluyn z(bGnSIb@l1W#ym*Ic5Si7HZOoL4&9d>XWL)t7=zmt9`XjX{XxLQ~h_6_&bQ!)lOW+ z2TI}t#ZOgD?IV9Zt`N1R>Nn8 z4A{~AVDgv8CWHF(p`wNx)roo!S9P_811hMgH~VXN78OI=o|QT1_mLa$v40D_Vk?7&iAXg=L5lrpsP>;U4p(rVf=w8^cOk@ z^`0W+8rTQ+gJtjv_!8^^Ti|8z4R{v(2=;-WKns0=DAuJjoqUhM>sUVp!}r(V4e&h} z@_hzFy{}-%_Y(|#{sxh%9TUEvhQc@xU4*dR9vAi*dJlIbQ�`UQ6fbU_-Iw8AT+_e1#6Jo7c|IJF}Ww)cySkCn)RT=itB zDQe1ZAKOkwM@wWm^hl~!Y|}Mk)ed?Q1r>$Lbp!2@iZ$!9=GlCmtw`(8LrSA%*)-O( zMVG5Oo7&7Bs~UW+EU{(TQXz=V2rpBb@c1s{<18Md@kpAKZ}EilXaSdHD5+f`ys=SvH2zzs)Y%6JQaW0kUz|N`0q+-ucSDP;y4^%6FSq>dW+9ZGptUt&o%GrB z>KrQ{#)XQj(z01yGj*l&l$Kv9AH84?rIvW$&`QO~y7Dv`=EEaVrNFxvY|hw*OQ~+Q zmo6Kbpq*(psBgwR%VIh(K*N;xXK_sLQ%(_%^}Q@P*qY4lglYQ(pNu)(-R&Gf3@_nK zj5A4TA|lUP(ich#+BL*b+cq2MAs&KnYPhwqh(ik9L=*L3$^zy zR8kuTza5u$V}gAO*)qWcJIZR)wP-h_ZK1k!+K@+G_h?0%rZ7Lgi*>po@IOfM5934p AuK)l5 diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index 9b6e5a67001bb1c57f47158e5685b0dca6e54e2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3523 zcmd6oONq+9)l0Vt5B2ccTnuskkmtP1UBGdcrW}lo4=9GFC~}~^KWLH zfIj0t;Nx&VqDUU^LfPjFxE3x!gs0&yxD`gQ3w{Mfk6)nZHIJaH@JYB0o`6rlAK_E* zcX$;pCuylM>Pxc~xC3T=IQy!_E)Uoq1ee-e@X)khpPYss&v&(5{ zYh&P6YmukJu;W#AHC(Tx>{UIz&#HzqR#LomTbr=ffwjr^qQD8G_RDO`N5jZ(7+;~a zDIK^t4y^$lI?-t0m{?L@y;EIH258PQ`|v7L$8 z=pbHISo25g73DOW+6k1?@V%$qcNTjm zH5B;!bvd#JEB3282MJuV7>#bL1JcK&xe`R=!y>@b)L`HG#&0g8B&|M|9cApy+hU&C*-QMB{ zjj*J=rWuC)#q}zE?eFr`ihi}KdwtKN#b)! z94D>!RT7^xQ(w!J8J|yDZzpjpi7zl_{rM!GkbxMo>U3&2>j%{(D_cjC_+rvJp2TO_ zC5b;X`79?>NB&-lnZGcY|@tZiFRa<2^Rf-~&$>5gB$zXZ`SBg+*dW zN$ki*ol{_!6ah1>XMvC2hlDquQEq@e(pObsrf6!x=6g5mU!2uw%ObELt6AfE|VQM9x_ zrQ1xW<0tKRDeDYQX5J@1BGMu0!OFLdC(=#Mqz;WaZqq(b&sBZ~K2F0j&1ZsjMscj!nJZDYO>@eXl&H+j(@~u% zX-!|w_=8DJGl^O!^6N~tCjv75G%IjN-WaBr9#tU`$(RcPQ8-NWJ<$;g)|paPK8q0! oGVwYN+W#}=jsT53z-DW-uu7m z`f>Z#PXyXa=r5q}*doLP_~?E3L;D(h8e9b{;5ta)ci@BI@8HAWpWut&miw_5q>=%+ z7xM;4;5#MX2Oq)wi;_3N-I(77w}an;?B^$t7(&x5akkAWw_ zC&77e8~83*1$*EF;AbG`@g?{=cnh2Ye+GAfJ7IJa8q`6~`v)Y+_P>Dy{snU0yRkXP zw-4M0R>8-?OC=@9dZge1@Z*wqLH73x$m{bk>6#OvN+ka4nui=Xh9q-iLGJ#<_ER+*q&Y(0Lzjd(b&nZk!|6g>&P^ns8$c zSda0>`ifKDE8}%yXts^Nc^NBl+Ul_DjdE^mNc&@L8WbFytR0|OUT+Xa6XFb3D=W?< z##`z9#^7G&ne$1U@8!gqVxqCJ6Vu8`pIMp5QtVaRyw!}6tw_;D70Py>npXA;KjgAB zO{^ECK~xwZo<8NiHw;E8<|C(!-V^sp|K#f9LKdQaysrlnU6s@LjMLG87mUZaEc#-YQn)~0H;%0(RP02vq; zaXlNfBwJR~;B$jajzzjJi zGO^*Lw)md8=i_%827p<-K#)h-V_TKg_q)jwCgKt zt3F>eKDo!T!KceADt3)<(G*k1LGW}s>4%w#vR<(|zcI%4oN+x(O_d_vJZ>z})KSi> zwH0kNDc{p3QtK;TTag?4+<55!-p0ARLWE-2O8S}4#Q3C)=>Ty=)F8f6Hos4G&mp@c zl2-OcFV|P1Y;7eIMdW&L17}tt6US*&D;d5&ts-r`8r+}@I*v4Q5=%)W=47ER?whL75wTv&N5CTM|hOh*z lYO>GA?%$5i%`eQ&6n@|t3;%n4o-g&K=c`FCBbQi;zX1j%wblRt diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100644 index df28844377825330994e4df73a664295880533b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2338 zcma)+T}&KR6vuD1ez4Z6RqI!6u1}WMp<9raE@Difr6i@0c5UsGneJY8$L!2(W@hCh zF{!Z#B*2meDFRKPsX(d%jl{wNRbNefs!t~R;?8XMi5UB0?1TR^GYbo;O>c7dch8;k zeP;HL9b3O(Si7-zVQ<^QSSff9q&5BsV*zjiCp8)>>Uj?_|@@a4v_$;^= zdN(>x0+L=5d>I_|@8^B_Ctv;zqe}NSDUy%CrCYnzS zfuz?62Entw-0kxcco6qvU?q4Pq_`z8Lb-13lqcQ2giSqq4x4&O{%OI4y?~9->_u#p z=+=Z0xUm8DIyTLN7WI24_VXn8i+V+i-W9Z(;Wcp=&5G7`Y?^oRqPemoh7yZgnlR0x zBj2McT8K*r%7SlkRc;G$oJv`(&@5rFT3xdY*|gRU|EHcZEnVde5nVG`ttTk1P$x{; zN*S`H=$daF+!*SpCZA6TenQ0LNIMT3a=Yh;o2g_{H!S8WBs>M=)6QMrYYG&WpOjU> z+>@zv6rBn|{pt=MEM3>)ipG;ln@IRqNjaiuu?+%mRjfGFthnG5nl)%qB_dn8!5iw> z3DIJ)CNi_y3)~d2yt1;CH5pN1P&C&?vu-MGKh`b`(IO0?MTE&tiDW{K2rg@dGARQd zDQYTjG0<#eq>?@jm7QK|GCM6S-WrEHH)ppaZqLlPo=QZyoJq$z-l$sMM z6EB;IS1f>fF=VOHj44s+NGfJZVLikH%}vrN@v%aNQk`sx5HAmwS4hD_Qm~32s0>xS zy)Rf53ut8*)NArW>jm;#$%b&6)$%+&k6;s{BlHEYF84yte?1J@6?>R{qcgkk zEwg7Ao!LRMTsu94@tv;g_RL6jvBw_0<&1Z+&2s*$8}_AMcrEsY&-;FP49w;Rr=81F zPS0>|bl7v~49+^epECPF&)mrNKwoZZj(Jx0T*jVVCCPSYoE-<(7X^D6@^ zec@UKGp(QSuWRJCojUm0jt}t<13e4K++=5q6!7np2Xm@3D{d4x%wB7lA hc4??MF+Yn3o4Nl3_p$P>oVj^>(a*#gTC|tb>_3zVL{|U+ diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json deleted file mode 100644 index 5024157..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Adds AppIndicator, KStatusNotifierItem and legacy Tray icons support to the Shell", - "gettext-domain": "AppIndicatorExtension", - "name": "AppIndicator and KStatusNotifierItem Support", - "settings-schema": "org.gnome.shell.extensions.appindicator", - "shell-version": [ - "45" - ], - "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator", - "uuid": "appindicatorsupport@rgcjonas.gmail.com", - "version": 57 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js deleted file mode 100644 index ce4c3f3..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -export function argbToRgba(src) { - const dest = new Uint8Array(src.length); - - for (let j = 0; j < src.length; j += 4) { - const srcAlpha = src[j]; - - dest[j] = src[j + 1]; /* red */ - dest[j + 1] = src[j + 2]; /* green */ - dest[j + 2] = src[j + 3]; /* blue */ - dest[j + 3] = srcAlpha; /* alpha */ - } - - return dest; -} - -export function getBestPixmap(pixmapsVariant, preferredSize) { - if (!pixmapsVariant) - throw new TypeError('null pixmapsVariant'); - - const pixmapsVariantsArray = new Array(pixmapsVariant.n_children()); - if (!pixmapsVariantsArray.length) - throw TypeError('Empty Icon found'); - - for (let i = 0; i < pixmapsVariantsArray.length; ++i) - pixmapsVariantsArray[i] = pixmapsVariant.get_child_value(i); - - const pixmapsSizedArray = pixmapsVariantsArray.map((pixmapVariant, index) => ({ - width: pixmapVariant.get_child_value(0).unpack(), - height: pixmapVariant.get_child_value(1).unpack(), - index, - })); - - const sortedIconPixmapArray = pixmapsSizedArray.sort( - ({width: widthA, height: heightA}, {width: widthB, height: heightB}) => { - const areaA = widthA * heightA; - const areaB = widthB * heightB; - - return areaA - areaB; - }); - - // we prefer any pixmap that is equal or bigger than our requested size - const qualifiedIconPixmapArray = sortedIconPixmapArray.filter(({width, height}) => - width >= preferredSize && height >= preferredSize); - - const {width, height, index} = qualifiedIconPixmapArray.length > 0 - ? qualifiedIconPixmapArray[0] : sortedIconPixmapArray.pop(); - - const pixmapVariant = pixmapsVariantsArray[index].get_child_value(2); - const rowStride = width * 4; // hopefully this is correct - - return {pixmapVariant, width, height, rowStride}; -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js deleted file mode 100644 index 625bc10..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js +++ /dev/null @@ -1,326 +0,0 @@ -// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- - -/* exported init, buildPrefsWidget */ - -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - -import { - ExtensionPreferences, - gettext as _ -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const AppIndicatorPreferences = GObject.registerClass( -class AppIndicatorPreferences extends Gtk.Box { - _init(extension) { - super._init({orientation: Gtk.Orientation.VERTICAL, spacing: 30}); - this._settings = extension.getSettings(); - - let label = null; - let widget = null; - - this.preferences_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 8, - margin_start: 30, - margin_end: 30, - margin_top: 30, - margin_bottom: 30, - }); - this.custom_icons_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - - label = new Gtk.Label({ - label: _('Enable Legacy Tray Icons support'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.Switch({halign: Gtk.Align.END}); - - this._settings.bind('legacy-tray-enabled', widget, 'active', - Gio.SettingsBindFlags.DEFAULT); - - this.legacy_tray_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - - this.legacy_tray_hbox.append(label); - this.legacy_tray_hbox.append(widget); - - // Icon opacity - this.opacity_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Opacity (min: 0, max: 255)'), - hexpand: true, - halign: Gtk.Align.START, - }); - - widget = new Gtk.SpinButton({halign: Gtk.Align.END}); - widget.set_sensitive(true); - widget.set_range(0, 255); - widget.set_value(this._settings.get_int('icon-opacity')); - widget.set_increments(1, 2); - widget.connect('value-changed', w => { - this._settings.set_int('icon-opacity', w.get_value_as_int()); - }); - this.opacity_hbox.append(label); - this.opacity_hbox.append(widget); - - // Icon saturation - this.saturation_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Desaturation (min: 0.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(0.0, 1.0); - widget.set_value(this._settings.get_double('icon-saturation')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-saturation', w.get_value()); - }); - this.saturation_hbox.append(label); - this.saturation_hbox.append(widget); - - // Icon brightness - this.brightness_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Brightness (min: -1.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(-1.0, 1.0); - widget.set_value(this._settings.get_double('icon-brightness')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-brightness', w.get_value()); - }); - this.brightness_hbox.append(label); - this.brightness_hbox.append(widget); - - // Icon contrast - this.contrast_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Contrast (min: -1.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(-1.0, 1.0); - widget.set_value(this._settings.get_double('icon-contrast')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-contrast', w.get_value()); - }); - this.contrast_hbox.append(label); - this.contrast_hbox.append(widget); - - // Icon size - this.icon_size_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Icon size (min: 0, max: 96)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END}); - widget.set_sensitive(true); - widget.set_range(0, 96); - widget.set_value(this._settings.get_int('icon-size')); - widget.set_increments(1, 2); - widget.connect('value-changed', w => { - this._settings.set_int('icon-size', w.get_value_as_int()); - }); - this.icon_size_hbox.append(label); - this.icon_size_hbox.append(widget); - - // Tray position in panel - this.tray_position_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Tray horizontal alignment'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.ComboBoxText(); - widget.append('center', _('Center')); - widget.append('left', _('Left')); - widget.append('right', _('Right')); - this._settings.bind('tray-pos', widget, 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this.tray_position_hbox.append(label); - this.tray_position_hbox.append(widget); - - this.preferences_vbox.append(this.legacy_tray_hbox); - this.preferences_vbox.append(this.opacity_hbox); - this.preferences_vbox.append(this.saturation_hbox); - this.preferences_vbox.append(this.brightness_hbox); - this.preferences_vbox.append(this.contrast_hbox); - this.preferences_vbox.append(this.icon_size_hbox); - this.preferences_vbox.append(this.tray_position_hbox); - - // Custom icons section - - const customListStore = new Gtk.ListStore(); - customListStore.set_column_types([ - GObject.TYPE_STRING, - GObject.TYPE_STRING, - GObject.TYPE_STRING, - ]); - const customInitArray = this._settings.get_value('custom-icons').deep_unpack(); - customInitArray.forEach(pair => { - customListStore.set(customListStore.append(), [0, 1, 2], pair); - }); - customListStore.append(); - - const customTreeView = new Gtk.TreeView({ - model: customListStore, - hexpand: true, - vexpand: true, - }); - const customTitles = [ - _('Indicator ID'), - _('Icon Name'), - _('Attention Icon Name'), - ]; - const indicatorIdColumn = new Gtk.TreeViewColumn({ - title: customTitles[0], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - const customIconColumn = new Gtk.TreeViewColumn({ - title: customTitles[1], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - const customAttentionIconColumn = new Gtk.TreeViewColumn({ - title: customTitles[2], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - - const cellrenderer = new Gtk.CellRendererText({editable: true}); - - indicatorIdColumn.pack_start(cellrenderer, true); - customIconColumn.pack_start(cellrenderer, true); - customAttentionIconColumn.pack_start(cellrenderer, true); - indicatorIdColumn.add_attribute(cellrenderer, 'text', 0); - customIconColumn.add_attribute(cellrenderer, 'text', 1); - customAttentionIconColumn.add_attribute(cellrenderer, 'text', 2); - customTreeView.insert_column(indicatorIdColumn, 0); - customTreeView.insert_column(customIconColumn, 1); - customTreeView.insert_column(customAttentionIconColumn, 2); - customTreeView.set_grid_lines(Gtk.TreeViewGridLines.BOTH); - - this.custom_icons_vbox.append(customTreeView); - - cellrenderer.connect('edited', (w, path, text) => { - this.selection = customTreeView.get_selection(); - const title = customTreeView.get_cursor()[1].get_title(); - const columnIndex = customTitles.indexOf(title); - const selection = this.selection.get_selected(); - const iter = selection.at(2); - const text2 = customListStore.get_value(iter, columnIndex ? 0 : 1); - customListStore.set(iter, [columnIndex], [text]); - const storeLength = customListStore.iter_n_children(null); - const customIconArray = []; - - for (let i = 0; i < storeLength; i++) { - const returnIter = customListStore.iter_nth_child(null, i); - const [success, iterList] = returnIter; - if (!success) - break; - - if (iterList) { - const id = customListStore.get_value(iterList, 0); - const customIcon = customListStore.get_value(iterList, 1); - const customAttentionIcon = customListStore.get_value(iterList, 2); - if (id && customIcon) - customIconArray.push([id, customIcon, customAttentionIcon || '']); - } else { - break; - } - } - this._settings.set_value('custom-icons', new GLib.Variant( - 'a(sss)', customIconArray)); - if (storeLength === 1 && (text || text2)) - customListStore.append(); - - if (storeLength > 1) { - if ((!text && !text2) && (storeLength - 1 > path)) - customListStore.remove(iter); - if ((text || text2) && storeLength - 1 <= path) - customListStore.append(); - } - }); - - this.notebook = new Gtk.Notebook(); - this.notebook.append_page(this.preferences_vbox, - new Gtk.Label({label: _('Preferences')})); - this.notebook.append_page(this.custom_icons_vbox, - new Gtk.Label({label: _('Custom Icons')})); - - this.append(this.notebook); - } -}); - -export default class DockPreferences extends ExtensionPreferences { - getPreferencesWidget() { - return new AppIndicatorPreferences(this); - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js deleted file mode 100644 index 2749b03..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js +++ /dev/null @@ -1,324 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Meta from 'gi://GdkPixbuf'; - -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -export class CancellablePromise extends Promise { - constructor(executor, cancellable) { - if (!(executor instanceof Function)) - throw TypeError('executor is not a function'); - - if (cancellable && !(cancellable instanceof Gio.Cancellable)) - throw TypeError('cancellable parameter is not a Gio.Cancellable'); - - let rejector; - let resolver; - super((resolve, reject) => { - resolver = resolve; - rejector = reject; - }); - - const {stack: promiseStack} = new Error(); - this._promiseStack = promiseStack; - - this._resolver = (...args) => { - resolver(...args); - this._resolved = true; - this._cleanup(); - }; - this._rejector = (...args) => { - rejector(...args); - this._rejected = true; - this._cleanup(); - }; - - if (!cancellable) { - executor(this._resolver, this._rejector); - return; - } - - this._cancellable = cancellable; - this._cancelled = cancellable.is_cancelled(); - if (this._cancelled) { - this._rejector(new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.CANCELLED, 'Promise cancelled')); - return; - } - - this._cancellationId = cancellable.connect(() => { - const id = this._cancellationId; - this._cancellationId = 0; - GLib.idle_add(GLib.PRIORITY_DEFAULT, () => cancellable.disconnect(id)); - this.cancel(); - }); - - executor(this._resolver, this._rejector); - } - - _cleanup() { - if (this._cancellationId) - this._cancellable.disconnect(this._cancellationId); - } - - get cancellable() { - return this._chainRoot._cancellable || null; - } - - get _chainRoot() { - return this._root ? this._root : this; - } - - then(...args) { - const ret = super.then(...args); - - /* Every time we call then() on this promise we'd get a new - * CancellablePromise however that won't have the properties that the - * root one has set, and then it won't be possible to cancel a promise - * chain from the last one. - * To allow this we keep track of the root promise, make sure that - * the same method on the root object is called during cancellation - * or any destruction method if you want this to work. */ - if (ret instanceof CancellablePromise) - ret._root = this._chainRoot; - - return ret; - } - - resolved() { - return !!this._chainRoot._resolved; - } - - rejected() { - return !!this._chainRoot._rejected; - } - - cancelled() { - return !!this._chainRoot._cancelled; - } - - pending() { - return !this.resolved() && !this.rejected(); - } - - cancel() { - if (this._root) { - this._root.cancel(); - return this; - } - - if (!this.pending()) - return this; - - this._cancelled = true; - const error = new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.CANCELLED, 'Promise cancelled'); - error.stack += `## Promise created at:\n${this._promiseStack}`; - this._rejector(error); - - return this; - } -} - -export class SignalConnectionPromise extends CancellablePromise { - constructor(object, signal, cancellable) { - if (arguments.length === 1 && object instanceof Function) { - super(object); - return; - } - - if (!(object.connect instanceof Function)) - throw new TypeError('Not a valid object'); - - if (object instanceof GObject.Object && - !GObject.signal_lookup(signal.split(':')[0], object.constructor.$gtype)) - throw new TypeError(`Signal ${signal} not found on object ${object}`); - - let id; - let destroyId; - super(resolve => { - let connectSignal; - if (object instanceof GObject.Object) - connectSignal = (sig, cb) => GObject.signal_connect(object, sig, cb); - else - connectSignal = (sig, cb) => object.connect(sig, cb); - - id = connectSignal(signal, (_obj, ...args) => { - if (!args.length) - resolve(); - else - resolve(args.length === 1 ? args[0] : args); - }); - - if (signal !== 'destroy' && - (!(object instanceof GObject.Object) || - GObject.signal_lookup('destroy', object.constructor.$gtype))) - destroyId = connectSignal('destroy', () => this.cancel()); - }, cancellable); - - this._object = object; - this._id = id; - this._destroyId = destroyId; - } - - _cleanup() { - if (this._id) { - let disconnectSignal; - - if (this._object instanceof GObject.Object) - disconnectSignal = id => GObject.signal_handler_disconnect(this._object, id); - else - disconnectSignal = id => this._object.disconnect(id); - - disconnectSignal(this._id); - if (this._destroyId) { - disconnectSignal(this._destroyId); - this._destroyId = 0; - } - this._object = null; - this._id = 0; - } - - super._cleanup(); - } - - get object() { - return this._chainRoot._object; - } -} - -export class GSourcePromise extends CancellablePromise { - constructor(gsource, priority, cancellable) { - if (arguments.length === 1 && gsource instanceof Function) { - super(gsource); - return; - } - - if (gsource.constructor.$gtype !== GLib.Source.$gtype) - throw new TypeError(`gsource ${gsource} is not of type GLib.Source`); - - if (priority === undefined) - priority = GLib.PRIORITY_DEFAULT; - else if (!Number.isInteger(priority)) - throw TypeError('Invalid priority'); - - super(resolve => { - gsource.set_priority(priority); - gsource.set_callback(() => { - resolve(); - return GLib.SOURCE_REMOVE; - }); - gsource.attach(null); - }, cancellable); - - this._gsource = gsource; - this._gsource.set_name(`[gnome-shell] ${this.constructor.name} ${ - new Error().stack.split('\n').filter(line => - !line.match(/misc\/promiseUtils\.js/))[0]}`); - - if (this.rejected()) - this._gsource.destroy(); - } - - get gsource() { - return this._chainRoot._gsource; - } - - _cleanup() { - if (this._gsource) { - this._gsource.destroy(); - this._gsource = null; - } - super._cleanup(); - } -} - -export class IdlePromise extends GSourcePromise { - constructor(priority, cancellable) { - if (arguments.length === 1 && priority instanceof Function) { - super(priority); - return; - } - - if (priority === undefined) - priority = GLib.PRIORITY_DEFAULT_IDLE; - - super(GLib.idle_source_new(), priority, cancellable); - } -} - -export class TimeoutPromise extends GSourcePromise { - constructor(interval, priority, cancellable) { - if (arguments.length === 1 && interval instanceof Function) { - super(interval); - return; - } - - if (!Number.isInteger(interval) || interval < 0) - throw TypeError('Invalid interval'); - - super(GLib.timeout_source_new(interval), priority, cancellable); - } -} - -export class TimeoutSecondsPromise extends GSourcePromise { - constructor(interval, priority, cancellable) { - if (arguments.length === 1 && interval instanceof Function) { - super(interval); - return; - } - - if (!Number.isInteger(interval) || interval < 0) - throw TypeError('Invalid interval'); - - super(GLib.timeout_source_new_seconds(interval), priority, cancellable); - } -} - -export class MetaLaterPromise extends CancellablePromise { - constructor(laterType, cancellable) { - if (arguments.length === 1 && laterType instanceof Function) { - super(laterType); - return; - } - - if (laterType && laterType.constructor.$gtype !== Meta.LaterType.$gtype) - throw new TypeError(`laterType ${laterType} is not of type Meta.LaterType`); - else if (!laterType) - laterType = Meta.LaterType.BEFORE_REDRAW; - - let id; - super(resolve => { - id = Meta.later_add(laterType, () => { - this.remove(); - resolve(); - return GLib.SOURCE_REMOVE; - }); - }, cancellable); - - this._id = id; - } - - _cleanup() { - if (this._id) { - Meta.later_remove(this._id); - this._id = 0; - } - super._cleanup(); - } -} - -export function _promisifySignals(proto) { - if (proto.connect_once) - return; - - proto.connect_once = function (signal, cancellable) { - return new SignalConnectionPromise(this, signal, cancellable); - }; -} - -_promisifySignals(GObject.Object.prototype); -_promisifySignals(Signals.EventEmitter.prototype); diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled deleted file mode 100644 index 65205698b60039cf60a82462b73d42df360ec14a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 820 zcmYjP&ubJh7|qtMZhwdc5j^y!;tVn~6?#_+VujvXq{n7w!)#!i43o6DEtPt!ClUMu zL=*%)c<4pEDE<>3ym{$y!5?@K>U)_T-N2jo^77?N=F4~YzO1w~UW~_O@Mf)}sm27i zs_E~o@!EBs&%oaVZvh_<9?r22 z)NS~E@H61ri~Z+}r@jFHHTW24>PF4Fk-q{PCr7UsPtEud_z!US=7tKEk6aug5sel1uMM!$i}M}l z?RLTdCn6a+=i)knt$HfFoj`d*-jK!VJ;ix5a9&zU-^V;dLu8>Lvd|FO|AxpW8zK|J z)w!hKsia58G}&s#z3_XXFHnjw*e7jZ7GQs{hj_1$ryKs%DCgiz4CJZLVU0`?dJy*= Ys6yt$B$P=R*&V1}*whkHHy&^Q3q9SVH~;_u diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml deleted file mode 100644 index 75bba7c..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - true - Enable legacy tray icons support - - - 0.0 - Saturation - - - 0.0 - Brightness - - - 0.0 - Contrast - - - 240 - Opacity - - - 0 - Icon size - Icon size in pixel - - - 12 - Icon spacing - Icon spacing within the tray - - - "right" - Position in tray - Set where the Icon tray should appear in Gnome tray - - - 1 - Order in tray - Set where the Icon tray should appear among other trays - - - [] - Custom icons - Replace any icons with custom icons from themes - - - diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js deleted file mode 100644 index 6d943b9..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -let settingsManager; - -export class SettingsManager { - static initialize(extension) { - SettingsManager._settingsManager = new SettingsManager(extension); - } - - static destroy() { - SettingsManager._settingsManager.destroy(); - SettingsManager._settingsManager = null; - } - - static getDefault() { - return this._settingsManager; - } - - get gsettings() { - return this._gsettings; - } - - constructor(extension) { - if (settingsManager) - throw new Error('SettingsManager is already constructed'); - - this._gsettings = extension.getSettings(); - } - - destroy() { - this._gsettings = null; - } -} - -export function getDefault() { - return SettingsManager.getDefault(); -} - -export function getDefaultGSettings() { - return SettingsManager.getDefault().gsettings; -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js deleted file mode 100644 index 915c860..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js +++ /dev/null @@ -1,287 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - -import * as AppIndicator from './appIndicator.js'; -import * as IndicatorStatusIcon from './indicatorStatusIcon.js'; -import * as Interfaces from './interfaces.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; -import * as DBusMenu from './dbusMenu.js'; - -import {DBusProxy} from './dbusProxy.js'; - - -// TODO: replace with org.freedesktop and /org/freedesktop when approved -const KDE_PREFIX = 'org.kde'; - -export const WATCHER_BUS_NAME = `${KDE_PREFIX}.StatusNotifierWatcher`; -const WATCHER_OBJECT = '/StatusNotifierWatcher'; - -const DEFAULT_ITEM_OBJECT_PATH = '/StatusNotifierItem'; - -/* - * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object - */ -export class StatusNotifierWatcher { - constructor(watchDog) { - this._watchDog = watchDog; - this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(Interfaces.StatusNotifierWatcher, this); - try { - this._dbusImpl.export(Gio.DBus.session, WATCHER_OBJECT); - } catch (e) { - Util.Logger.warn(`Failed to export ${WATCHER_OBJECT}`); - logError(e); - } - this._cancellable = new Gio.Cancellable(); - this._everAcquiredName = false; - this._ownName = Gio.DBus.session.own_name(WATCHER_BUS_NAME, - Gio.BusNameOwnerFlags.NONE, - this._acquiredName.bind(this), - this._lostName.bind(this)); - this._items = new Map(); - - try { - this._dbusImpl.emit_signal('StatusNotifierHostRegistered', null); - } catch (e) { - Util.Logger.warn(`Failed to notify registered host ${WATCHER_OBJECT}`); - } - - this._seekStatusNotifierItems().catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'Looking for StatusNotifierItem\'s'); - }); - } - - _acquiredName() { - this._everAcquiredName = true; - this._watchDog.nameAcquired = true; - } - - _lostName() { - if (this._everAcquiredName) - Util.Logger.debug(`Lost name${WATCHER_BUS_NAME}`); - else - Util.Logger.warn(`Failed to acquire ${WATCHER_BUS_NAME}`); - this._watchDog.nameAcquired = false; - } - - async _registerItem(service, busName, objPath) { - const id = Util.indicatorId(service, busName, objPath); - - if (this._items.has(id)) { - Util.Logger.warn(`Item ${id} is already registered`); - return; - } - - Util.Logger.debug(`Registering StatusNotifierItem ${id}`); - - try { - const indicator = new AppIndicator.AppIndicator(service, busName, objPath); - this._items.set(id, indicator); - indicator.connect('destroy', () => this._onIndicatorDestroyed(indicator)); - - indicator.connect('name-owner-changed', async () => { - if (!indicator.hasNameOwner) { - try { - await new PromiseUtils.TimeoutPromise(500, - GLib.PRIORITY_DEFAULT, this._cancellable); - if (this._items.has(id) && !indicator.hasNameOwner) - indicator.destroy(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - }); - - // if the desktop is not ready delay the icon creation and signal emissions - await Util.waitForStartupCompletion(indicator.cancellable); - const statusIcon = new IndicatorStatusIcon.IndicatorStatusIcon(indicator); - IndicatorStatusIcon.addIconToPanel(statusIcon); - - this._dbusImpl.emit_signal('StatusNotifierItemRegistered', - GLib.Variant.new('(s)', [indicator.uniqueId])); - this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', - GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - throw e; - } - } - - async _ensureItemRegistered(service, busName, objPath) { - const id = Util.indicatorId(service, busName, objPath); - const item = this._items.get(id); - - if (item) { - // delete the old one and add the new indicator - Util.Logger.debug(`Attempting to re-register ${id}; resetting instead`); - item.reset(); - return; - } - - await this._registerItem(service, busName, objPath); - } - - async _seekStatusNotifierItems() { - // Some indicators (*coff*, dropbox, *coff*) do not re-register again - // when the plugin is enabled/disabled, thus we need to manually look - // for the objects in the session bus that implements the - // StatusNotifierItem interface... However let's do it after a low - // priority idle, so that it won't affect startup. - const cancellable = this._cancellable; - const bus = Gio.DBus.session; - const uniqueNames = await Util.getBusNames(bus, cancellable); - const introspectName = async name => { - const nodes = Util.introspectBusObject(bus, name, cancellable, - ['org.kde.StatusNotifierItem']); - const services = [...uniqueNames.get(name)]; - - for await (const node of nodes) { - const {path} = node; - const ids = services.map(s => Util.indicatorId(s, name, path)); - if (ids.every(id => !this._items.has(id))) { - const service = services.find(s => - s && s.startsWith('org.kde.StatusNotifierItem')) || services[0]; - const id = Util.indicatorId( - path === DEFAULT_ITEM_OBJECT_PATH ? service : null, - name, path); - Util.Logger.warn(`Using Brute-force mode for StatusNotifierItem ${id}`); - this._registerItem(service, name, path); - } - } - }; - await Promise.allSettled([...uniqueNames.keys()].map(n => introspectName(n))); - } - - async RegisterStatusNotifierItemAsync(params, invocation) { - // it would be too easy if all application behaved the same - // instead, ayatana patched gnome apps to send a path - // while kde apps send a bus name - const [service] = params; - let busName, objPath; - - if (service.charAt(0) === '/') { // looks like a path - busName = invocation.get_sender(); - objPath = service; - } else if (service.match(Util.BUS_ADDRESS_REGEX)) { - try { - busName = await Util.getUniqueBusName(invocation.get_connection(), - service, this._cancellable); - } catch (e) { - logError(e); - } - objPath = DEFAULT_ITEM_OBJECT_PATH; - } - - if (!busName || !objPath) { - const error = `Impossible to register an indicator for parameters '${ - service.toString()}'`; - Util.Logger.warn(error); - - invocation.return_dbus_error('org.gnome.gjs.JSError.ValueError', - error); - return; - } - - try { - await this._ensureItemRegistered(service, busName, objPath); - invocation.return_value(null); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - invocation.return_dbus_error('org.gnome.gjs.JSError.ValueError', - e.message); - } - } - - _onIndicatorDestroyed(indicator) { - const {uniqueId} = indicator; - this._items.delete(uniqueId); - - try { - this._dbusImpl.emit_signal('StatusNotifierItemUnregistered', - GLib.Variant.new('(s)', [uniqueId])); - this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', - GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } catch (e) { - Util.Logger.warn(`Failed to emit signals: ${e}`); - } - } - - RegisterStatusNotifierHostAsync(_service, invocation) { - invocation.return_error_literal( - Gio.DBusError, - Gio.DBusError.NOT_SUPPORTED, - 'Registering additional notification hosts is not supported'); - } - - IsNotificationHostRegistered() { - return true; - } - - get RegisteredStatusNotifierItems() { - return Array.from(this._items.values()).map(i => i.uniqueId); - } - - get IsStatusNotifierHostRegistered() { - return true; - } - - get ProtocolVersion() { - return 0; - } - - destroy() { - if (this._isDestroyed) - return; - - // this doesn't do any sync operation and doesn't allow us to hook up - // the event of being finished which results in our unholy debounce hack - // (see extension.js) - this._items.forEach(indicator => indicator.destroy()); - this._cancellable.cancel(); - - try { - this._dbusImpl.emit_signal('StatusNotifierHostUnregistered', null); - } catch (e) { - Util.Logger.warn(`Failed to emit uinregistered signal: ${e}`); - } - - Gio.DBus.session.unown_name(this._ownName); - - try { - this._dbusImpl.unexport(); - } catch (e) { - Util.Logger.warn(`Failed to unexport watcher object: ${e}`); - } - - DBusMenu.DBusClient.destroy(); - AppIndicator.AppIndicatorProxy.destroy(); - DBusProxy.destroy(); - Util.destroyDefaultTheme(); - - this._dbusImpl.run_dispose(); - delete this._dbusImpl; - - delete this._items; - this._isDestroyed = true; - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js deleted file mode 100644 index cdc2a8e..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js +++ /dev/null @@ -1,104 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Shell from 'gi://Shell'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as IndicatorStatusIcon from './indicatorStatusIcon.js'; -import * as Util from './util.js'; -import * as SettingsManager from './settingsManager.js'; - -let trayIconsManager; - -export class TrayIconsManager extends Signals.EventEmitter { - static initialize() { - if (!trayIconsManager) - trayIconsManager = new TrayIconsManager(); - return trayIconsManager; - } - - static destroy() { - trayIconsManager.destroy(); - } - - constructor() { - super(); - - if (trayIconsManager) - throw new Error('TrayIconsManager is already constructed'); - - this._changedId = SettingsManager.getDefaultGSettings().connect( - 'changed::legacy-tray-enabled', () => this._toggle()); - - this._toggle(); - } - - _toggle() { - if (SettingsManager.getDefaultGSettings().get_boolean('legacy-tray-enabled')) - this._enable(); - else - this._disable(); - } - - _enable() { - if (this._tray) - return; - - this._tray = new Shell.TrayManager(); - Util.connectSmart(this._tray, 'tray-icon-added', this, this.onTrayIconAdded); - Util.connectSmart(this._tray, 'tray-icon-removed', this, this.onTrayIconRemoved); - - this._tray.manage_screen(Main.panel); - } - - _disable() { - if (!this._tray) - return; - - IndicatorStatusIcon.getTrayIcons().forEach(i => i.destroy()); - if (this._tray.unmanage_screen) { - this._tray.unmanage_screen(); - this._tray = null; - } else { - // FIXME: This is very ugly, but it's needed by old shell versions - this._tray = null; - imports.system.gc(); // force finalizing tray to unmanage screen - } - } - - onTrayIconAdded(_tray, icon) { - const trayIcon = new IndicatorStatusIcon.IndicatorStatusTrayIcon(icon); - IndicatorStatusIcon.addIconToPanel(trayIcon); - } - - onTrayIconRemoved(_tray, icon) { - try { - const [trayIcon] = IndicatorStatusIcon.getTrayIcons().filter(i => i.icon === icon); - trayIcon.destroy(); - } catch (e) { - Util.Logger.warning(`No icon container found for ${icon.title} (${icon})`); - } - } - - destroy() { - this.emit('destroy'); - SettingsManager.getDefaultGSettings().disconnect(this._changedId); - this._disable(); - trayIconsManager = null; - } -} diff --git a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js b/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js deleted file mode 100644 index d2cb352..0000000 --- a/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js +++ /dev/null @@ -1,434 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// 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. - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -const ByteArray = imports.byteArray; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Config from 'resource:///org/gnome/shell/misc/config.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import {BaseStatusIcon} from './indicatorStatusIcon.js'; - -export const BUS_ADDRESS_REGEX = /([a-zA-Z0-9._-]+\.[a-zA-Z0-9.-]+)|(:[0-9]+\.[0-9]+)$/; - -Gio._promisify(Gio.DBusConnection.prototype, 'call'); -Gio._promisify(Gio._LocalFilePrototype, 'read'); -Gio._promisify(Gio.InputStream.prototype, 'read_bytes_async'); - -export function indicatorId(service, busName, objectPath) { - if (service !== busName && service?.match(BUS_ADDRESS_REGEX)) - return service; - - return `${busName}@${objectPath}`; -} - -export async function getUniqueBusName(bus, name, cancellable) { - if (name[0] === ':') - return name; - - if (!bus) - bus = Gio.DBus.session; - - const variantName = new GLib.Variant('(s)', [name]); - const [unique] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'GetNameOwner', variantName, new GLib.VariantType('(s)'), - Gio.DBusCallFlags.NONE, -1, cancellable)).deep_unpack(); - - return unique; -} - -export async function getBusNames(bus, cancellable) { - if (!bus) - bus = Gio.DBus.session; - - const [names] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'ListNames', null, new GLib.VariantType('(as)'), Gio.DBusCallFlags.NONE, - -1, cancellable)).deep_unpack(); - - const uniqueNames = new Map(); - const requests = names.map(name => getUniqueBusName(bus, name, cancellable)); - const results = await Promise.allSettled(requests); - - for (let i = 0; i < results.length; i++) { - const result = results[i]; - if (result.status === 'fulfilled') { - let namesForBus = uniqueNames.get(result.value); - if (!namesForBus) { - namesForBus = new Set(); - uniqueNames.set(result.value, namesForBus); - } - namesForBus.add(result.value !== names[i] ? names[i] : null); - } else if (!result.reason.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Logger.debug(`Impossible to get the unique name of ${names[i]}: ${result.reason}`); - } - } - - return uniqueNames; -} - -async function getProcessId(connectionName, cancellable = null, bus = Gio.DBus.session) { - const res = await bus.call('org.freedesktop.DBus', '/', - 'org.freedesktop.DBus', 'GetConnectionUnixProcessID', - new GLib.Variant('(s)', [connectionName]), - new GLib.VariantType('(u)'), - Gio.DBusCallFlags.NONE, - -1, - cancellable); - const [pid] = res.deepUnpack(); - return pid; -} - -export async function getProcessName(connectionName, cancellable = null, - priority = GLib.PRIORITY_DEFAULT, bus = Gio.DBus.session) { - const pid = await getProcessId(connectionName, cancellable, bus); - const cmdFile = Gio.File.new_for_path(`/proc/${pid}/cmdline`); - const inputStream = await cmdFile.read_async(priority, cancellable); - const bytes = await inputStream.read_bytes_async(2048, priority, cancellable); - return ByteArray.toString(bytes.toArray().map(v => !v ? 0x20 : v)); -} - -export async function* introspectBusObject(bus, name, cancellable, - interfaces = undefined, path = undefined) { - if (!path) - path = '/'; - - const [introspection] = (await bus.call(name, path, 'org.freedesktop.DBus.Introspectable', - 'Introspect', null, new GLib.VariantType('(s)'), Gio.DBusCallFlags.NONE, - 5000, cancellable)).deep_unpack(); - - const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspection); - - if (!interfaces || dbusNodeImplementsInterfaces(nodeInfo, interfaces)) - yield {nodeInfo, path}; - - if (path === '/') - path = ''; - - for (const subNodeInfo of nodeInfo.nodes) { - const subPath = `${path}/${subNodeInfo.path}`; - yield* introspectBusObject(bus, name, cancellable, interfaces, subPath); - } -} - -function dbusNodeImplementsInterfaces(nodeInfo, interfaces) { - if (!(nodeInfo instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces)) - return false; - - return interfaces.some(iface => nodeInfo.lookup_interface(iface)); -} - -export class NameWatcher extends Signals.EventEmitter { - constructor(name) { - super(); - - this._watcherId = Gio.DBus.session.watch_name(name, - Gio.BusNameWatcherFlags.NONE, () => { - this._nameOnBus = true; - Logger.debug(`Name ${name} appeared`); - this.emit('changed'); - this.emit('appeared'); - }, () => { - this._nameOnBus = false; - Logger.debug(`Name ${name} vanished`); - this.emit('changed'); - this.emit('vanished'); - }); - } - - destroy() { - this.emit('destroy'); - - Gio.DBus.session.unwatch_name(this._watcherId); - delete this._watcherId; - } - - get nameOnBus() { - return !!this._nameOnBus; - } -} - -function connectSmart3A(src, signal, handler) { - const id = src.connect(signal, handler); - let destroyId = 0; - - if (src.connect && (!(src instanceof GObject.Object) || GObject.signal_lookup('destroy', src))) { - destroyId = src.connect('destroy', () => { - src.disconnect(id); - src.disconnect(destroyId); - }); - } - - return [id, destroyId]; -} - -function connectSmart4A(src, signal, target, method) { - if (typeof method !== 'function') - throw new TypeError('Unsupported function'); - - method = method.bind(target); - const signalId = src.connect(signal, method); - const onDestroy = () => { - src.disconnect(signalId); - if (srcDestroyId) - src.disconnect(srcDestroyId); - if (tgtDestroyId) - target.disconnect(tgtDestroyId); - }; - - // GObject classes might or might not have a destroy signal - // JS Classes will not complain when connecting to non-existent signals - const srcDestroyId = src.connect && (!(src instanceof GObject.Object) || - GObject.signal_lookup('destroy', src)) ? src.connect('destroy', onDestroy) : 0; - const tgtDestroyId = target.connect && (!(target instanceof GObject.Object) || - GObject.signal_lookup('destroy', target)) ? target.connect('destroy', onDestroy) : 0; - - return [signalId, srcDestroyId, tgtDestroyId]; -} - -// eslint-disable-next-line valid-jsdoc -/** - * Connect signals to slots, and remove the connection when either source or - * target are destroyed - * - * Usage: - * Util.connectSmart(srcOb, 'signal', tgtObj, 'handler') - * or - * Util.connectSmart(srcOb, 'signal', () => { ... }) - */ -export function connectSmart(...args) { - if (arguments.length === 4) - return connectSmart4A(...args); - else - return connectSmart3A(...args); -} - -function disconnectSmart3A(src, signalIds) { - const [id, destroyId] = signalIds; - src.disconnect(id); - - if (destroyId) - src.disconnect(destroyId); -} - -function disconnectSmart4A(src, tgt, signalIds) { - const [signalId, srcDestroyId, tgtDestroyId] = signalIds; - - disconnectSmart3A(src, [signalId, srcDestroyId]); - - if (tgtDestroyId) - tgt.disconnect(tgtDestroyId); -} - -export function disconnectSmart(...args) { - if (arguments.length === 2) - return disconnectSmart3A(...args); - else if (arguments.length === 3) - return disconnectSmart4A(...args); - - throw new TypeError('Unexpected number of arguments'); -} - -let _defaultTheme; -export function getDefaultTheme() { - if (_defaultTheme) - return _defaultTheme; - - _defaultTheme = new St.IconTheme(); - return _defaultTheme; -} - -export function destroyDefaultTheme() { - _defaultTheme = null; -} - -// eslint-disable-next-line valid-jsdoc -/** - * Helper function to wait for the system startup to be completed. - * Adding widgets before the desktop is ready to accept them can result in errors. - */ -export async function waitForStartupCompletion(cancellable) { - if (Main.layoutManager._startingUp) - await Main.layoutManager.connect_once('startup-complete', cancellable); -} - -/** - * Helper class for logging stuff - */ -export class Logger { - static _logStructured(logLevel, message, extraFields = {}) { - if (!Object.values(GLib.LogLevelFlags).includes(logLevel)) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, - 'logLevel is not a valid GLib.LogLevelFlags'); - return; - } - - if (!Logger._levels.includes(logLevel)) - return; - - let fields = { - 'SYSLOG_IDENTIFIER': this.uuid, - 'MESSAGE': `${message}`, - }; - - let thisFile = null; - const {stack} = new Error(); - for (let stackLine of stack.split('\n')) { - stackLine = stackLine.replace('resource:///org/gnome/Shell/', ''); - const [code, line] = stackLine.split(':'); - const [func, file] = code.split(/@(.+)/); - - if (!thisFile || thisFile === file) { - thisFile = file; - continue; - } - - fields = Object.assign(fields, { - 'CODE_FILE': file || '', - 'CODE_LINE': line || '', - 'CODE_FUNC': func || '', - }); - - break; - } - - GLib.log_structured(Logger._domain, logLevel, Object.assign(fields, extraFields)); - } - - static init(extension) { - if (Logger._domain) - return; - - const allLevels = Object.values(GLib.LogLevelFlags); - const domains = GLib.getenv('G_MESSAGES_DEBUG'); - const {name: domain} = extension.metadata; - this.uuid = extension.metadata.uuid; - Logger._domain = domain.replaceAll(' ', '-'); - - if (domains === 'all' || (domains && domains.split(' ').includes(Logger._domain))) { - Logger._levels = allLevels; - } else { - Logger._levels = allLevels.filter( - l => l <= GLib.LogLevelFlags.LEVEL_WARNING); - } - } - - static debug(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_DEBUG, message); - } - - static message(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_MESSAGE, message); - } - - static warn(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, message); - } - - static error(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_ERROR, message); - } - - static critical(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_CRITICAL, message); - } -} - -export function versionCheck(required) { - const current = Config.PACKAGE_VERSION; - const currentArray = current.split('.'); - const [major] = currentArray; - return major >= required; -} - -export function tryCleanupOldIndicators() { - const indicatorType = BaseStatusIcon; - const indicators = Object.values(Main.panel.statusArea).filter(i => i instanceof indicatorType); - - try { - const panelBoxes = [ - Main.panel._leftBox, Main.panel._centerBox, Main.panel._rightBox, - ]; - - panelBoxes.forEach(box => - indicators.push(...box.get_children().filter(i => i instanceof indicatorType))); - } catch (e) { - logError(e); - } - - new Set(indicators).forEach(i => i.destroy()); -} - -export const CancellableChild = GObject.registerClass({ - Properties: { - 'parent': GObject.ParamSpec.object( - 'parent', 'parent', 'parent', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - Gio.Cancellable.$gtype), - }, -}, -class CancellableChild extends Gio.Cancellable { - _init(parent) { - if (parent && !(parent instanceof Gio.Cancellable)) - throw TypeError('Not a valid cancellable'); - - super._init({parent}); - - if (parent) { - if (parent.is_cancelled()) { - this.cancel(); - return; - } - - this._connectToParent(); - } - } - - _connectToParent() { - this._connectId = this.parent.connect(() => { - this._realCancel(); - - if (this._disconnectIdle) - return; - - this._disconnectIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - delete this._disconnectIdle; - this._disconnectFromParent(); - return GLib.SOURCE_REMOVE; - }); - }); - } - - _disconnectFromParent() { - if (this._connectId && !this._disconnectIdle) { - this.parent.disconnect(this._connectId); - delete this._connectId; - } - } - - _realCancel() { - Gio.Cancellable.prototype.cancel.call(this); - } - - cancel() { - this._disconnectFromParent(); - this._realCancel(); - } -}); diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js deleted file mode 100644 index bad6405..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js +++ /dev/null @@ -1,262 +0,0 @@ -import Shell from 'gi://Shell'; -import Clutter from 'gi://Clutter'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../effects/paint_signals.js'; -const Tweener = imports.tweener.tweener; - -const transparent = Clutter.Color.from_pixel(0x00000000); -const FOLDER_DIALOG_ANIMATION_TIME = 200; - -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; -}; - - -export const AppFoldersBlur = class AppFoldersBlur { - constructor(connections, settings, _) { - this.connections = connections; - this.paint_signals = new PaintSignals(connections); - this.settings = settings; - } - - enable() { - this._log("blurring appfolders"); - - brightness = this.settings.appfolder.CUSTOMIZE - ? this.settings.appfolder.BRIGHTNESS - : this.settings.BRIGHTNESS; - sigma = this.settings.appfolder.CUSTOMIZE - ? this.settings.appfolder.SIGMA - : this.settings.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.settings.HACKS_LEVEL === 1 || this.settings.HACKS_LEVEL === 2) - this._log(`appfolders hack level ${this.settings.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.settings.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.settings.HACKS_LEVEL === 1 || this.settings.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.settings.appfolder.BLUR) - this.blur_appfolders(); - } - - set_brightness(b) { - brightness = b; - if (this.settings.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.settings.DEBUG) - console.log(`[Blur my Shell > appfolders] ${str}`); - } -}; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js deleted file mode 100644 index 8334473..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js +++ /dev/null @@ -1,548 +0,0 @@ -import Shell from 'gi://Shell'; -import Clutter from 'gi://Clutter'; -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../effects/paint_signals.js'; -import { ApplicationsService } from '../dbus/services.js'; - - -export const ApplicationsBlur = class ApplicationsBlur { - constructor(connections, settings, _) { - this.connections = connections; - this.settings = settings; - this.paint_signals = new PaintSignals(connections); - - // 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.settings.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.settings.applications.ENABLE_ALL; - let whitelist = this.settings.applications.WHITELIST; - let blacklist = this.settings.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.settings.applications.CUSTOMIZE) { - brightness = this.settings.applications.BRIGHTNESS; - sigma = this.settings.applications.SIGMA; - } else { - brightness = this.settings.BRIGHTNESS; - sigma = this.settings.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.settings.applications.CUSTOMIZE) { - brightness = this.settings.applications.BRIGHTNESS; - sigma = this.settings.applications.SIGMA; - } else { - brightness = this.settings.BRIGHTNESS; - sigma = this.settings.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.settings.HACKS_LEVEL === 1 || this.settings.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.settings.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.settings.applications.OPACITY); - - this.connections.connect( - window_actor, - 'notify::opacity', - _ => this.set_window_opacity(window_actor, this.settings.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.settings.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) - 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(); - // check if the window is using wayland, or xwayland/xorg for rendering - const scale = is_wayland && meta_window.get_client_type() == 0 - ? 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.settings.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.settings.DEBUG) - console.log(`[Blur my Shell > applications] ${str}`); - } -}; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js deleted file mode 100644 index 3c56588..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js +++ /dev/null @@ -1,322 +0,0 @@ -import St from 'gi://St'; -import Shell from 'gi://Shell'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -const Signals = imports.signals; - -import { PaintSignals } from '../effects/paint_signals.js'; - -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, settings) { - // 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.settings = settings; - this.old_style = this.dash._background.style; - - dash_blur.connections.connect(dash_blur, 'remove-dashes', () => { - this._log("removing blur from dash"); - this.dash.get_parent().remove_child(this.background_parent); - this.dash._background.style = this.old_style; - - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); - }); - - 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.settings.dash_to_dock.STYLE_DASH_TO_DOCK] - ); - }); - - dash_blur.connections.connect(dash_blur, 'reset-background', () => { - this.dash._background.style = this.old_style; - - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); - }); - - dash_blur.connections.connect(dash_blur, 'show', () => { - this.effect.sigma = this.dash_blur.sigma; - }); - - dash_blur.connections.connect(dash_blur, 'hide', () => { - this.effect.sigma = 0; - }); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > dash] ${str}`); - } -} - -export const DashBlur = class DashBlur { - constructor(connections, settings, _) { - this.dashes = []; - this.connections = connections; - this.settings = settings; - this.paint_signals = new PaintSignals(connections); - this.sigma = this.settings.dash_to_dock.CUSTOMIZE - ? this.settings.dash_to_dock.SIGMA - : this.settings.SIGMA; - this.brightness = this.settings.dash_to_dock.CUSTOMIZE - ? this.settings.dash_to_dock.BRIGHTNESS - : this.settings.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.settings.HACKS_LEVEL === 1) { - this._log("dash hack level 1"); - this.paint_signals.disconnect_all(); - - let rp = () => { - effect.queue_repaint(); - }; - - dash._box.get_children().forEach((icon) => { - try { - let zone = icon.get_child_at_index(0); - - this.connections.connect(zone, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - } catch (e) { - this._warn(`${e}, continuing`); - } - }); - - this.connections.connect(dash._box, 'actor-added', (_, actor) => { - try { - let zone = actor.get_child_at_index(0); - - this.connections.connect(zone, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - } catch (e) { - this._warn(`${e}, continuing`); - } - }); - - let show_apps = dash._showAppsIcon; - - this.connections.connect(show_apps, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - - this.connections.connect(dash, 'leave-event', rp); - } else if (this.settings.HACKS_LEVEL === 2) { - this._log("dash hack level 2"); - - this.paint_signals.connect(background, effect); - } else { - this.paint_signals.disconnect_all(); - } - - // create infos - let infos = new DashInfos( - this, dash, background_parent, effect, this.settings - ); - - // 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.settings.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.settings.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.settings.DEBUG) - console.log(`[Blur my Shell > dash manager] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > dash manager] ${str}`); - } -}; - -Signals.addSignalMethods(DashBlur.prototype); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js deleted file mode 100644 index bd10908..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js +++ /dev/null @@ -1,167 +0,0 @@ -import St from 'gi://St'; -import Shell from 'gi://Shell'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Background from 'resource:///org/gnome/shell/ui/background.js'; -import { UnlockDialog } from 'resource:///org/gnome/shell/ui/unlockDialog.js'; - -let sigma; -let brightness; -let color; -let noise; -let lightness; - -const original_createBackground = - UnlockDialog.prototype._createBackground; -const original_updateBackgroundEffects = - UnlockDialog.prototype._updateBackgroundEffects; - - -export const LockscreenBlur = class LockscreenBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.effects_manager = effects_manager; - } - - enable() { - this._log("blurring lockscreen"); - - brightness = this.settings.lockscreen.CUSTOMIZE - ? this.settings.lockscreen.BRIGHTNESS - : this.settings.BRIGHTNESS; - sigma = this.settings.lockscreen.CUSTOMIZE - ? this.settings.lockscreen.SIGMA - : this.settings.SIGMA; - color = this.settings.lockscreen.CUSTOMIZE - ? this.settings.lockscreen.COLOR - : this.settings.COLOR; - noise = this.settings.lockscreen.CUSTOMIZE - ? this.settings.lockscreen.NOISE_AMOUNT - : this.settings.NOISE_AMOUNT; - lightness = this.settings.lockscreen.CUSTOMIZE - ? this.settings.lockscreen.NOISE_LIGHTNESS - : this.settings.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 = global.blur_my_shell._lockscreen_blur.effects_manager.new_color_effect({ - name: 'color', - color: color - }, this.settings); - - let noise_effect = global.blur_my_shell._lockscreen_blur.effects_manager.new_noise_effect({ - name: 'noise', - noise: noise, - lightness: lightness - }, this.settings); - - 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('color'); - const noise_effect = widget.get_effect('noise'); - 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.settings.DEBUG) - console.log(`[Blur my Shell > lockscreen] ${str}`); - } -}; diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js deleted file mode 100644 index 6f5150c..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js +++ /dev/null @@ -1,309 +0,0 @@ -import Shell from 'gi://Shell'; -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { WorkspaceAnimationController } from 'resource:///org/gnome/shell/ui/workspaceAnimation.js'; -const wac_proto = WorkspaceAnimationController.prototype; - -const OVERVIEW_COMPONENTS_STYLE = [ - "", - "overview-components-light", - "overview-components-dark", - "overview-components-transparent" -]; - - -export const OverviewBlur = class OverviewBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.effects = []; - this.settings = settings; - this.effects_manager = effects_manager; - 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.settings.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, true - ); - - 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.settings.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.effects = outer_this.effects.filter( - effects_group => !effects_group.is_transition - ); - - 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 - this.remove_background_actors(); - - // add new backgrounds - Main.layoutManager.monitors.forEach(monitor => { - const bg_actor = this.create_background_actor(monitor, false); - - Main.layoutManager.overviewGroup.insert_child_at_index( - bg_actor, - monitor.index - ); - }); - } - - create_background_actor(monitor, is_transition) { - let bg_actor = new Meta.BackgroundActor({ - meta_display: global.display, - monitor: monitor.index - }); - let background_group = Main.layoutManager._backgroundGroup - .get_children() - .filter((child) => child instanceof Meta.BackgroundActor); - let background = - background_group[ - Main.layoutManager.monitors.length - monitor.index - 1 - ]; - - if (!background) { - this._warn("could not get background for overview"); - return bg_actor; - } - - bg_actor.content.set({ - background: background.get_content().background - }); - - let blur_effect = new Shell.BlurEffect({ - brightness: this.settings.overview.CUSTOMIZE - ? this.settings.overview.BRIGHTNESS - : this.settings.BRIGHTNESS, - sigma: this.settings.overview.CUSTOMIZE - ? this.settings.overview.SIGMA - : this.settings.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 = this.effects_manager.new_color_effect({ - color: this.settings.overview.CUSTOMIZE - ? this.settings.overview.COLOR - : this.settings.COLOR - }, this.settings); - - let noise_effect = this.effects_manager.new_noise_effect({ - noise: this.settings.overview.CUSTOMIZE - ? this.settings.overview.NOISE_AMOUNT - : this.settings.NOISE_AMOUNT, - lightness: this.settings.overview.CUSTOMIZE - ? this.settings.overview.NOISE_LIGHTNESS - : this.settings.NOISE_LIGHTNESS - }, this.settings); - - 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, is_transition }); - - 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.settings.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; - }); - } - - remove_background_actors() { - Main.layoutManager.overviewGroup.get_children().forEach(actor => { - if (actor.constructor.name === 'Meta_BackgroundActor') { - actor.get_effects().forEach(effect => { - this.effects_manager.remove(effect); - }); - Main.layoutManager.overviewGroup.remove_child(actor); - actor.destroy(); - } - }); - this.effects = []; - } - - disable() { - this._log("removing blur from overview"); - this.remove_background_actors(); - 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.connections.disconnect_all(); - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > overview] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > overview] ${str}`); - } -}; diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js deleted file mode 100644 index a904f92..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js +++ /dev/null @@ -1,695 +0,0 @@ -import St from 'gi://St'; -import Shell from 'gi://Shell'; -import Meta from 'gi://Meta'; -import Mtk from 'gi://Mtk'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../effects/paint_signals.js'; - -const DASH_TO_PANEL_UUID = 'dash-to-panel@jderose9.github.com'; -const PANEL_STYLES = [ - "transparent-panel", - "light-panel", - "dark-panel", - "contrasted-panel" -]; - - -export const PanelBlur = class PanelBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.window_signal_ids = new Map(); - this.settings = settings; - this.effects_manager = effects_manager; - 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.settings.dash_to_panel.BLUR_ORIGINAL_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.settings.panel.STATIC_BLUR - ? new Meta.BackgroundActor({ - meta_display: global.display, - monitor: monitor.index - }) - : 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.settings.panel.CUSTOMIZE - ? this.settings.panel.BRIGHTNESS - : this.settings.BRIGHTNESS, - sigma: this.settings.panel.CUSTOMIZE - ? this.settings.panel.SIGMA - : this.settings.SIGMA - * monitor.geometry_scale, - mode: this.settings.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 = this.effects_manager.new_color_effect({ - color: this.settings.panel.CUSTOMIZE - ? this.settings.panel.COLOR - : this.settings.COLOR - }, this.settings); - - let noise = this.effects_manager.new_noise_effect({ - noise: this.settings.panel.CUSTOMIZE - ? this.settings.panel.NOISE_AMOUNT - : this.settings.NOISE_AMOUNT, - lightness: this.settings.panel.CUSTOMIZE - ? this.settings.panel.NOISE_LIGHTNESS - : this.settings.NOISE_LIGHTNESS - }, this.settings); - - 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.settings.panel.STATIC_BLUR; - - // reset widgets to right state - actors.widgets.background_parent.remove_child(actors.widgets.background); - this.effects_manager.remove(actors.effects.blur); - this.effects_manager.remove(actors.effects.color); - this.effects_manager.remove(actors.effects.noise); - - // create new background actor - actors.widgets.background = is_static - ? new Meta.BackgroundActor({ - meta_display: global.display, - monitor: this.find_monitor_for(actors.widgets.panel).index - }) - : 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.settings.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.settings.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.settings.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.content.set({ - background: bg.get_content().background - }); - else - this._warn("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.settings.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 Mtk.Rectangle({ - x: extents.get_x(), - y: extents.get_y(), - width: extents.get_width(), - height: extents.get_height(), - }); - - let index = global.display.get_monitor_index_for_rect(rect); - - return Main.layoutManager.monitors[index]; - } - - /// 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.settings.panel.BLUR && - this.settings.panel.UNBLUR_IN_OVERVIEW - ) { - if (!this.settings.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.settings.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.settings.panel.OVERRIDE_BACKGROUND - && - should_override - ) - panel.add_style_class_name( - PANEL_STYLES[this.settings.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.settings.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(); - }); - } - - // destroy every blurred background left, necessary after sleep - destroy_blur_effects() { - Main.panel?.get_parent()?.get_children().forEach( - child => { - if (child.name === 'topbar-blurred-background-parent') { - child.get_children().forEach(meta_background_actor => { - meta_background_actor.get_effects().forEach(effect => { - this.effects_manager.remove(effect); - }); - }); - child.destroy_all_children(); - child.destroy(); - } - } - ); - } - - 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); - this.effects_manager.remove(actors.effects.noise); - this.effects_manager.remove(actors.effects.color); - this.effects_manager.remove(actors.effects.blur); - try { - actors.widgets.panel_box.remove_child( - actors.widgets.background_parent - ); - } catch (e) { } - actors.widgets.background_parent?.destroy(); - }); - - this.destroy_blur_effects(); - - this.actors_list = []; - - this.connections.disconnect_all(); - - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > panel] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > panel] ${str}`); - } -}; diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js deleted file mode 100644 index 34bb3c4..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js +++ /dev/null @@ -1,173 +0,0 @@ -import Shell from 'gi://Shell'; -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - - -export const ScreenshotBlur = class ScreenshotBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.effects = []; - this.settings = settings; - this.effects_manager = effects_manager; - } - - 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({ - meta_display: global.display, - monitor: monitor.index - }); - let background = Main.layoutManager._backgroundGroup.get_child_at_index( - Main.layoutManager.monitors.length - monitor.index - 1 - ); - - if (!background) { - this._warn("could not get background for screenshot's window selector"); - return bg_actor; - } - - bg_actor.content.set({ - background: background.get_content().background - }); - - let blur_effect = new Shell.BlurEffect({ - brightness: this.settings.screenshot.CUSTOMIZE - ? this.settings.screenshot.BRIGHTNESS - : this.settings.BRIGHTNESS, - sigma: this.settings.screenshot.CUSTOMIZE - ? this.settings.screenshot.SIGMA - : this.settings.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 = this.effects_manager.new_color_effect({ - color: this.settings.screenshot.CUSTOMIZE - ? this.settings.screenshot.COLOR - : this.settings.COLOR - }, this.settings); - - let noise_effect = this.effects_manager.new_noise_effect({ - noise: this.settings.screenshot.CUSTOMIZE - ? this.settings.screenshot.NOISE_AMOUNT - : this.settings.NOISE_AMOUNT, - lightness: this.settings.screenshot.CUSTOMIZE - ? this.settings.screenshot.NOISE_LIGHTNESS - : this.settings.NOISE_LIGHTNESS - }, this.settings); - - 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); - actor._blur_actor.destroy(); - } - }); - this.effects = []; - } - - disable() { - this._log("removing blur from screenshot's window selector"); - - this.remove(); - this.connections.disconnect_all(); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > screenshot] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > screenshot] ${str}`); - } -}; diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js deleted file mode 100644 index 6a60564..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js +++ /dev/null @@ -1,162 +0,0 @@ -import Shell from 'gi://Shell'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../effects/paint_signals.js'; - - -export const WindowListBlur = class WindowListBlur { - constructor(connections, settings, _) { - this.connections = connections; - this.settings = settings; - 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.settings.window_list.CUSTOMIZE - ? this.settings.window_list.SIGMA - : this.settings.SIGMA, - brightness: this.settings.window_list.CUSTOMIZE - ? this.settings.window_list.BRIGHTNESS - : this.settings.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.settings.HACKS_LEVEL === 1) { - this._log("window list hack level 1"); - - this.paint_signals.connect(child, blur_effect); - - } else if (this.settings.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.settings.window_list.CUSTOMIZE - ? this.settings.window_list.SIGMA - : this.settings.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.settings.DEBUG) - console.log(`[Blur my Shell > window list] ${str}`); - } -}; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/connections.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/connections.js deleted file mode 100644 index c15ef48..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/connections.js +++ /dev/null @@ -1,101 +0,0 @@ -import GObject from 'gi://GObject'; - -/// An object to easily manage signals. -export const 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._warn(`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._warn(`error removing connection: ${e}; continuing`); - } - }); - - // reset buffer - this.buffer = []; - } - - _warn(str) { - console.warn(`[Blur my Shell > connections] ${str}`); - } -}; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js deleted file mode 100644 index 7ef7b22..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js +++ /dev/null @@ -1,89 +0,0 @@ -import { ColorEffect } from '../effects/color_effect.js'; -import { NoiseEffect } from '../effects/noise_effect.js'; - - -/// An object to manage effects (by not destroying them all the time) -export const EffectsManager = class EffectsManager { - constructor(connections) { - this.connections = connections; - this.used = []; - this.color_effects = []; - this.noise_effects = []; - } - - connect_to_destroy(effect) { - effect.old_actor = effect.get_actor(); - if (effect.old_actor) - effect.old_actor_id = effect.old_actor.connect('destroy', _ => { - this.remove(effect); - }); - - this.connections.connect(effect, 'notify::actor', _ => { - let actor = effect.get_actor(); - - if (effect.old_actor && actor != effect.old_actor) - effect.old_actor.disconnect(effect.old_actor_id); - - if (actor) { - effect.old_actor_id = actor.connect('destroy', _ => { - this.remove(effect); - }); - } - }); - } - - new_color_effect(params, settings) { - let effect; - if (this.color_effects.length > 0) { - effect = this.color_effects.splice(0, 1)[0]; - effect.set(params); - } else - effect = new ColorEffect(params, settings); - - this.used.push(effect); - this.connect_to_destroy(effect); - return effect; - } - - new_noise_effect(params, settings) { - let effect; - if (this.noise_effects.length > 0) { - effect = this.noise_effects.splice(0, 1)[0]; - effect.set(params); - } else - effect = new NoiseEffect(params, settings); - - this.used.push(effect); - this.connect_to_destroy(effect); - return effect; - } - - remove(effect) { - effect.get_actor()?.remove_effect(effect); - if (effect.old_actor) - effect.old_actor.disconnect(effect.old_actor_id); - delete effect.old_actor; - delete effect.old_actor_id; - - let index = this.used.indexOf(effect); - if (index >= 0) { - this.used.splice(index, 1); - - if (effect instanceof ColorEffect) - this.color_effects.push(effect); - else if (effect instanceof NoiseEffect) - this.noise_effects.push(effect); - } - } - - destroy_all() { - this.used.forEach(effect => { this.remove(effect); }); - [ - this.used, - this.color_effects, - this.noise_effects - ].forEach(array => { - array.splice(0, array.length); - }); - } -}; diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js deleted file mode 100644 index 5a87ba4..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js +++ /dev/null @@ -1,131 +0,0 @@ -import { Type } from './settings.js'; - -// This lists the preferences keys -export const 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" }, - ] - }, - { - component: "dash-to-panel", schemas: [ - { type: Type.B, name: "blur-original-panel" }, - ] - }, -]; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/settings.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/settings.js deleted file mode 100644 index d2bef17..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/settings.js +++ /dev/null @@ -1,182 +0,0 @@ -import GLib from 'gi://GLib'; - -const Signals = imports.signals; - -/// An enum non-extensively describing the type of gsettings key. -export const 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 settings = new Settings([ -/// { 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. -export const Settings = class Settings { - constructor(keys, settings) { - this.settings = settings; - 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 Settings object. - get_property_name(name) { - return name.replaceAll('-', '_').toUpperCase(); - } - - /// Remove all connections managed by the Settings object, i.e. created with - /// `settings.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(Settings.prototype); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/client.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/client.js deleted file mode 100644 index 3867b3a..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/client.js +++ /dev/null @@ -1,58 +0,0 @@ -import Gio from '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. -export 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. -export 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. -export 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/iface.xml b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/iface.xml deleted file mode 100644 index 4f298ad..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/iface.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js deleted file mode 100644 index 9b566c2..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js +++ /dev/null @@ -1,90 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'; - - -export const ApplicationsService = class ApplicationsService { - constructor() { - let decoder = new TextDecoder(); - let path = GLib.filename_from_uri(GLib.uri_resolve_relative( - import.meta.url, 'iface.xml', GLib.UriFlags.NONE) - )[0]; - let [, buffer] = GLib.file_get_contents(path); - let iface = decoder.decode(buffer); - GLib.free(buffer); - - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.glsl b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.glsl deleted file mode 100644 index 142b89b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.glsl +++ /dev/null @@ -1,13 +0,0 @@ -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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.js deleted file mode 100644 index 2ae9191..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color_effect.js +++ /dev/null @@ -1,181 +0,0 @@ -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; - - -const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'color_effect.glsl', GLib.UriFlags.NONE))[0]; - - -const get_shader_source = _ => { - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// 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 -export const 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 { - constructor(params, settings) { - // initialize without color as a parameter - let _color = params.color; - delete params.color; - - super(params); - - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - this._static = true; - this._settings = settings; - - // 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() { - // don't anything if this._settings is undefined (when calling super) - if (this._settings === undefined) - return; - - this.set_enabled( - this.blend > 0 && - this._settings.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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl deleted file mode 100644 index 6d701b6..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.glsl +++ /dev/null @@ -1,20 +0,0 @@ -uniform sampler2D tex; -uniform float noise; -uniform float lightness; - -float PHI = 1.61803398874989484820459; -float SEED = 24; - -float noise_gen(in vec2 xy) { - float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x); - r = r != r ? 0.0 : r; - return r; -} - -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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.js deleted file mode 100644 index 8d9464c..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/noise_effect.js +++ /dev/null @@ -1,109 +0,0 @@ -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; - - -const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'noise_effect.glsl', GLib.UriFlags.NONE))[0]; - -const get_shader_source = _ => { - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -export const 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 { - constructor(params, settings) { - super(params); - - this._noise = null; - this._lightness = null; - - this._static = true; - this._settings = settings; - - if (params.noise) - this.noise = params.noise; - if (params.lightness) - this.lightness = params.lightness; - - // 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() { - // don't anything if this._settings is undefined (when calling super) - if (this._settings === undefined) - return; - - this.set_enabled( - this.noise > 0 && - this._settings.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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/paint_signals.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/paint_signals.js deleted file mode 100644 index 84a895b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/paint_signals.js +++ /dev/null @@ -1,89 +0,0 @@ -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - - -export const 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 = []; - } -}; - -export const 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js deleted file mode 100644 index 5aa7b9f..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js +++ /dev/null @@ -1,641 +0,0 @@ -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import { EffectsManager } from './conveniences/effects_manager.js'; -import { Connections } from './conveniences/connections.js'; -import { Settings } from './conveniences/settings.js'; -import { Keys } from './conveniences/keys.js'; - -import { PanelBlur } from './components/panel.js'; -import { OverviewBlur } from './components/overview.js'; -import { DashBlur } from './components/dash_to_dock.js'; -import { LockscreenBlur } from './components/lockscreen.js'; -import { AppFoldersBlur } from './components/appfolders.js'; -import { WindowListBlur } from './components/window_list.js'; -import { ApplicationsBlur } from './components/applications.js'; -import { ScreenshotBlur } from './components/screenshot.js'; - -// 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. -export default class BlurMyShell extends Extension { - /// Enables the extension - enable() { - // add the extension to global to make it accessible to other extensions - // create it first as it is very useful when debugging crashes - global.blur_my_shell = this; - - // create a Settings instance, to manage extension's preferences - // it needs to be loaded before logging, as it checks for DEBUG - this._settings = new Settings(Keys, this.getSettings()); - - this._log("enabling extension..."); - - // create main extension Connections instance - this._connection = new Connections; - - // store it in a global array - this._connections = [this._connection]; - - // create a global effects manager (to prevent RAM bleeding) - this._effects_manager = new EffectsManager(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._settings, this._effects_manager]; - }; - - this._panel_blur = new PanelBlur(...init()); - this._dash_to_dock_blur = new DashBlur(...init()); - this._overview_blur = new OverviewBlur(...init()); - this._lockscreen_blur = new LockscreenBlur(...init()); - this._appfolder_blur = new AppFoldersBlur(...init()); - this._window_list_blur = new WindowListBlur(...init()); - this._applications_blur = new ApplicationsBlur(...init()); - this._screenshot_blur = new ScreenshotBlur(...init()); - - // maybe disable clipped redraw - this._update_clipped_redraws(); - - // connect each component to preferences change - this._connect_to_settings(); - - // enable 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._settings.overview.BLUR && !this._overview_blur.enabled) - this._overview_blur.enable(); - } catch (e) { - this._log("Could not enable overview blur directly"); - this._log(e); - } - try { - if (this._settings.dash_to_dock.BLUR - && !this._dash_to_dock_blur.enabled) - this._dash_to_dock_blur.enable(); - } catch (e) { - this._log("Could not enable dash-to-dock blur directly"); - this._log(e); - } - try { - if (this._settings.panel.BLUR && !this._panel_blur.enabled) - this._panel_blur.enable(); - } catch (e) { - this._log("Could not enable panel blur directly"); - this._log(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._settings.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._settings = 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._settings.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._settings.panel.BLUR && !this._panel_blur.enabled) - this._panel_blur.enable(); - - if (this._settings.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled) - this._dash_to_dock_blur.enable(); - - if (this._settings.overview.BLUR && !this._overview_blur.enabled) - this._overview_blur.enable(); - - if (this._settings.lockscreen.BLUR) - this._lockscreen_blur.enable(); - - if (this._settings.appfolder.BLUR) - this._appfolder_blur.enable(); - - if (this._settings.applications.BLUR) - this._applications_blur.enable(); - - if (this._settings.window_list.BLUR) - this._window_list_blur.enable(); - - if (this._settings.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._settings.SIGMA_changed(() => { - this._update_sigma(); - }); - this._settings.BRIGHTNESS_changed(() => { - this._update_brightness(); - }); - this._settings.COLOR_changed(() => { - this._update_color(); - }); - this._settings.NOISE_AMOUNT_changed(() => { - this._update_noise_amount(); - }); - this._settings.NOISE_LIGHTNESS_changed(() => { - this._update_noise_lightness(); - }); - this._settings.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._settings.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._settings.overview.BLUR_changed(() => { - if (this._settings.overview.BLUR) { - this._overview_blur.enable(); - } else { - this._overview_blur.disable(); - } - }); - - // overview components style changed - this._settings.overview.STYLE_COMPONENTS_changed(() => { - if (this._settings.overview.BLUR) { - this._overview_blur.update_components_classname(); - } - }); - - - // ---------- APPFOLDER ---------- - - // toggled on/off - this._settings.appfolder.BLUR_changed(() => { - if (this._settings.appfolder.BLUR) { - this._appfolder_blur.enable(); - } else { - this._appfolder_blur.disable(); - } - }); - - // appfolder dialogs style changed - this._settings.appfolder.STYLE_DIALOGS_changed(() => { - if (this._settings.appfolder.BLUR) - this._appfolder_blur.blur_appfolders(); - }); - - - // ---------- PANEL ---------- - - // toggled on/off - this._settings.panel.BLUR_changed(() => { - if (this._settings.panel.BLUR) { - this._panel_blur.enable(); - } else { - this._panel_blur.disable(); - } - }); - - this._settings.COLOR_AND_NOISE_changed(() => { - // permits making sure that the blur is not washed out when disabling - // the other effects - if (this._settings.panel.BLUR) - this._panel_blur.invalidate_all_blur(); - }); - - // static blur toggled on/off - this._settings.panel.STATIC_BLUR_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.update_all_blur_type(); - }); - - // panel blur's overview connection toggled on/off - this._settings.panel.UNBLUR_IN_OVERVIEW_changed(() => { - this._panel_blur.connect_to_windows_and_overview(); - }); - - // panel override background toggled on/off - this._settings.panel.OVERRIDE_BACKGROUND_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - // panel style changed - this._settings.panel.STYLE_PANEL_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - // panel background's dynamic overriding toggled on/off - this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - - // ---------- DASH TO DOCK ---------- - - // toggled on/off - this._settings.dash_to_dock.BLUR_changed(() => { - if (this._settings.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._settings.dash_to_dock.STATIC_BLUR_changed(() => { - //if (this._settings.dash_to_dock.BLUR) - // this._dash_to_dock_blur.change_blur_type(); - }); - - // dash-to-dock override background toggled on/off - this._settings.dash_to_dock.OVERRIDE_BACKGROUND_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.update_background(); - }); - - // dash-to-dock style changed - this._settings.dash_to_dock.STYLE_DASH_TO_DOCK_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.update_background(); - }); - - // dash-to-dock blur's overview connection toggled on/off - this._settings.dash_to_dock.UNBLUR_IN_OVERVIEW_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.connect_to_overview(); - }); - - - // ---------- APPLICATIONS ---------- - - // toggled on/off - this._settings.applications.BLUR_changed(() => { - if (this._settings.applications.BLUR) { - this._applications_blur.enable(); - } else { - this._applications_blur.disable(); - } - }); - - // application opacity changed - this._settings.applications.OPACITY_changed(_ => { - if (this._settings.applications.BLUR) - this._applications_blur.set_opacity( - this._settings.applications.OPACITY - ); - }); - - // application blur-on-overview changed - this._settings.applications.BLUR_ON_OVERVIEW_changed(_ => { - if (this._settings.applications.BLUR) - this._applications_blur.connect_to_overview(); - }); - - // application enable-all changed - this._settings.applications.ENABLE_ALL_changed(_ => { - if (this._settings.applications.BLUR) - this._applications_blur.update_all_windows(); - }); - - // application whitelist changed - this._settings.applications.WHITELIST_changed(_ => { - if ( - this._settings.applications.BLUR - && !this._settings.applications.ENABLE_ALL - ) - this._applications_blur.update_all_windows(); - }); - - // application blacklist changed - this._settings.applications.BLACKLIST_changed(_ => { - if ( - this._settings.applications.BLUR - && this._settings.applications.ENABLE_ALL - ) - this._applications_blur.update_all_windows(); - }); - - - // ---------- LOCKSCREEN ---------- - - // toggled on/off - this._settings.lockscreen.BLUR_changed(() => { - if (this._settings.lockscreen.BLUR) { - this._lockscreen_blur.enable(); - } else { - this._lockscreen_blur.disable(); - } - }); - - - // ---------- WINDOW LIST ---------- - - // toggled on/off - this._settings.window_list.BLUR_changed(() => { - if (this._settings.window_list.BLUR) { - this._window_list_blur.enable(); - } else { - this._window_list_blur.disable(); - } - }); - - - // ---------- HIDETOPBAR ---------- - - // toggled on/off - this._settings.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(); - }); - - - // ---------- DASH TO PANEL ---------- - - // toggled on/off - this._settings.dash_to_panel.BLUR_ORIGINAL_PANEL_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.reset(); - }); - - - // ---------- SCREENSHOT ---------- - - // toggled on/off - this._settings.screenshot.BLUR_changed(() => { - if (this._settings.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_settings = this._settings[name]; - - // general values switch is toggled - component_settings.CUSTOMIZE_changed(() => { - if (component_settings.CUSTOMIZE) { - component.set_sigma(component_settings.SIGMA); - component.set_brightness(component_settings.BRIGHTNESS); - component.set_color(component_settings.COLOR); - component.set_noise_amount(component_settings.NOISE_AMOUNT); - component.set_noise_lightness(component_settings.NOISE_LIGHTNESS); - } - else { - component.set_sigma(this._settings.SIGMA); - component.set_brightness(this._settings.BRIGHTNESS); - component.set_color(this._settings.COLOR); - component.set_noise_amount(this._settings.NOISE_AMOUNT); - component.set_noise_lightness(this._settings.NOISE_LIGHTNESS); - } - }); - - // sigma is changed - component_settings.SIGMA_changed(() => { - if (component_settings.CUSTOMIZE) - component.set_sigma(component_settings.SIGMA); - else - component.set_sigma(this._settings.SIGMA); - }); - - // brightness is changed - component_settings.BRIGHTNESS_changed(() => { - if (component_settings.CUSTOMIZE) - component.set_brightness(component_settings.BRIGHTNESS); - else - component.set_brightness(this._settings.BRIGHTNESS); - }); - - // color is changed - component_settings.COLOR_changed(() => { - if (component_settings.CUSTOMIZE) - component.set_color(component_settings.COLOR); - else - component.set_color(this._settings.COLOR); - }); - - // noise amount is changed - component_settings.NOISE_AMOUNT_changed(() => { - if (component_settings.CUSTOMIZE) - component.set_noise_amount(component_settings.NOISE_AMOUNT); - else - component.set_noise_amount(this._settings.NOISE_AMOUNT); - }); - - // noise lightness is changed - component_settings.NOISE_LIGHTNESS_changed(() => { - if (component_settings.CUSTOMIZE) - component.set_noise_lightness(component_settings.NOISE_LIGHTNESS); - else - component.set_noise_lightness(this._settings.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_settings = this._settings[name]; - - // update sigma accordingly - if (component_settings.CUSTOMIZE) { - component.set_sigma(component_settings.SIGMA); - } - else { - component.set_sigma(this._settings.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_settings = this._settings[name]; - - // update brightness accordingly - if (component_settings.CUSTOMIZE) - component.set_brightness(component_settings.BRIGHTNESS); - else - component.set_brightness(this._settings.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_settings = this._settings[name]; - - // update color accordingly - if (component_settings.CUSTOMIZE) - component.set_color(component_settings.COLOR); - else - component.set_color(this._settings.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_settings = this._settings[name]; - - // update color accordingly - if (component_settings.CUSTOMIZE) - component.set_noise_amount(component_settings.NOISE_AMOUNT); - else - component.set_noise_amount(this._settings.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_settings = this._settings[name]; - - // update color accordingly - if (component_settings.CUSTOMIZE) - component.set_noise_lightness(component_settings.NOISE_LIGHTNESS); - else - component.set_noise_lightness(this._settings.NOISE_LIGHTNESS); - }); - } - - _log(str) { - if (this._settings.DEBUG) - console.log(`[Blur my Shell > extension] ${str}`); - } -} diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg deleted file mode 100644 index bdab309..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-window-symbolic.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg deleted file mode 100644 index 87f307f..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg deleted file mode 100644 index 2eda98b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg deleted file mode 100644 index 5a78b46..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg deleted file mode 100644 index e11da07..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/general-symbolic.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg deleted file mode 100644 index 8378c9c..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-filled-symbolic.svg +++ /dev/null @@ -1,40 +0,0 @@ - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg deleted file mode 100644 index 45e703e..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg deleted file mode 100644 index 445f662..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg deleted file mode 100644 index a8da14f..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-window-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg deleted file mode 100644 index e443de4..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg deleted file mode 100644 index cad2da8..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-mode-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg deleted file mode 100644 index cad2da8..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 4a999d6a07cd0453691f3d206c6ba8e6423db08e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12893 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 HWJg~CnG$az diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index f95a0e812e885da2b537a139519196eaa49755ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4362 zcmb7`-)|gO6~_lC&@NDZz4CC|mptHE+o>X@PJ^1JX{glvP-}iY&hB3C4w;=<&CJ@d zgpiXoNgJdF5C{nfsNspX#EBEfb~gV260@&>c*qO?2A}V}v$nT!gji|!?%X-|obUOb z?>RI7{?-e>4fuSO?|1nAjPE!3{)?|Z=5s+{SzlrO8|!se*)D!Q2wvxZ#M<*Oq3*Mg+JK}`>Up7m!e@(HXCQN(&VToh&0ij%lpHE~f4ZPDBprOZs(!)!1};&xQV zSz0vBVlOVR9t>*??>$mCb7#l zk8$2qin(@{WV@_Mjnaf_7qum$noe)k&eAf^5;)6N zOn*rJaVZMP!U;1@YmGToPoljYR_5dLYX$6vW4# zoow0W%duUlsT31l{zcZeCW%Tk0?vGjn2Gw|qqt>o27!8=*o&AKQYBtn5-MybS+{^@ zM8AwTDr-|$`_xhufaZ3PG@ zmC%tG(MUx*w}26Jde}rXSI?Gcb}-CoF6-lbrVxHU$XA&SCe@jW7CA-RyjHjq1XTAk z`ZKXzwQMsupJzX%CBk<*;SX&tLKYn6u)i8Q*}WMJQ(Inayzg=k&lKIb6TUU<7U5#H zU>fJoh40(tSO>$mA#K4No;&b&2m^q%{coWhtlpa>e_J8M*Riz)-dTtc?|t;^vZHjEX>aK zvZAz|=8A2p{>?1!&LSmcRLqKu-84RX)t%jQPsZKGnRm~e+M{5;IoCLe$m!8=adkji zC5o9HBvG6mW3)wiVaww`SbQfux@V{C7**k^w4HV0w7X!Aw&JpJ9vo2;BK&@_VA6rR zERG*OX8hmdsd?qNnLpO}ap7#~^L@A4#%_m=@uf+;O(L!<2EH$IcN_1c@ul%)uJ9sL{Ue{v z>3hxTJY7mV;~UkzYI}TB5PYUvZ0-19axkhM5acnzZpv-bRJYl4fJFw$jK&{pA-505 zSFqd?8Q46=<1RR;GeFw#AlLb`=BT_0FTWG+`!xlCxdJ0DH{*Of3b{#rAgA742cjw@ zY#>v~HmZjN--FvSmmMWmbxCDj~J6@dFR&7ta7@@a6lCiC%! z*lo%6A(sltInJekN0Ni{d8qmmEAignDJG4IJECcTm6~nqw1c+K#_xb zV@HIeL?mrCtT<#+6Gj;vgLr~xoH1hWo#fRvl2QGE(n!JZNhYV;8g5HFmG zu>)i~qxxSG)zxFjf(g8cS+&77D@t+HxFnxxD?}luQ$njYaLNr_)fp4OtKv@e$h`WT z%DgHGD(s$IMot;yk0$gf_uGJcI8|?tcZ(38Oj?ly#@A>HR%;3(5nQ_Os!1NI8l$tqxL}kUMyGWuYDe!GSZ5@!<71kssZl4x*!;e~7yyMuI>1P&Ia9+&7P0 zxP6{f)yE7gDPMVW#Fu*8X~zkTA3!)+adUkduErE}?aK<}w>7lHginIjphgeGzXa&V z_cOCj;OiRQ2hQl92O%oz9%AMq zO5id6cIT-dXcO6J=GDzFkRaXmtt9#cMUJIiH@(zFdWQX<&kLygR8jDV)`RLVE~M&m zeL|fYStCK->!?_hiAzVcJi%OaxT(4)FKLf+Q=^Nve!zTR(_sPE8T9i@KUxXypO=rE zFNN{Figit>pSE|9y@YhnF#bb^3t1;&kP%hTff%TczQ8-+4-wB8r?RZ3k3N+I1;+NAbBdf5rMe(T}f zwOR?h937mGG`c%~Oz83nU7;_z!iZ_{wD&mj)5|GDWpdqU1d^m>swQH}qfjqfp0Ul~ Ezi0~QTL1t6 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 2309a34cff58b035efb21cc836cf44c0107a2002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1402 zcmZWoJ&znk5FN0=)W}KKdT;9e_44U&5{xsjS7Afg z3$QO?ar^@N1NIp9BJANaN%9K(*YGdF{{$cJ{tEvY{O|BTz+QVcN&d$Aw^QAFKc7yL z*Rg&KPw;=jpN0Pi-oc-FE=h1LL3lf`Y~RIk@_e_|{^Qwh48~(mBi%R(mcmqs>sqUl zgR;iwG@L3=`1zo;rjZ1uNn^@*%36hGo(?Tl656XH@qwK9Mh8!|^ZIv_~6@Hme>U~;W8XP_>Pom&vEd97;&uW@ZneVA(!_^%UpDfshv#3 zi76#dX*H6;iQ1o7bO_&w^}m^1j%bnC&c)4@ERx$bm%x$?+oIYz*-2Z&LYc8$#OPq_ z|2A8?WHOO5tP|5zRa0>^XWa-bI-Y1|fmcfvDaeyOXFo@Dc4M4= zU7Utc`=ZyIS|4PbpSaVjJ1o8zX*dG#)T-p(@#6)RobKM(y><+~pKqjBtO;UJ@3ID< zAp4wni$Xd#HnTcHO#}FUZvG((i0; zQ#ai)bZ&?G+v%rS*H0}ocRL#BLf+rX`)M+mNF{2Y#^S|HY{@g!hOeu|LlaRFCD?}~ z2KO8Ed8Y&HL>X`(bRs(@1P5nFm>9GuI?U(k9-70B0982>?P-P9 o3mpGTxK53UI!qe8>j`LP7|TA{Bnm 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 2a7d711fda231b07e519c843dc8d2a9f811d4848..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11858 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 A(*OVf diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 5825103ff91832a7d306235661b301fef2caf5cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15185 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 594115a5c02c9301bad37e75742f68c291cf1c8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11464 zcmb7}ZHy$xS;x!qOY9{$U?6~jqvwJfUmK~!YB9X|BkOIL{4p77*ERaq)SbiGDsFuJ|Gbx@c~dQ z@q4Per@Lq8Y^Qa-|LK{os^|6pJXQCvcir+kipy~SEcg3wR_Zx$`8NJ=?Y~{A_ks_D zcY_zfB`^ga1D^)hz;A&Ty!{TP{sxS|p9CM_WeuJO-vwsiPl3;Z?*@Ml{1Na^K!&Jq zc0{6|pc|1Q`B@Bbmc{zdRO&u#GGn-~ucc>Z@5xfMM3!+!mXApg{mKR*sW4c-EN zF~=`~Kg#oqpp5%7@SWh-z#jv@3H}`T9q>``d*A_Z{dw;(1}uYvO3e}FRIe}P@_ z4e&f@F^2zL_XnW(>Hok(;Ocw)e4hsQ^Zc9ODe$jAdGAhw z^nUO(DDih0l=VLY%6gv%|CIRJ0p-057~uopGax2WUj-ZB%iuZiyWnMTmBFuqSHXM0 z-}o7&ei8gCDEfW}`~~peK!&K>NIqPsG$`xu1LgOFpyXc%yZ}B2iroJUikZHh{QfOa^5GRw^!Pha=DkUKdF}*%Ug2+0 zCz`o9^U|E+_%B6fd83)|Ajrw!Sk2F0eBmW;4+ng z!VjMValQIOP~`p#@HX(x+aec4{ zW*{M;UIRtW{|4nf5mwfDHz>cq2mA`y0L3n^fcJs_0^SPVa<6}H36$~ofFjRcQ2d;N z68F!7;@>ZVqTe5ZN5OA`9|qsSr1JZI@OJQVP~JNScECRP%iyb^#L)`D_!00DD0X}S zJPy7AX5dj?lDv2sl<)rsTmm2cpkMc6pxEaN;6?Cz;6d=jvbV=)L3#fLkfG{D@Fws{ zZqer!Zc@VOcnCbn%`5KuIDf@<@8l+&oSuNQi_9hY`ws4Ramyug$|doAmir9%DQ>xL zFpv3%nv*QpI{JBt$?MDFXfomd;CJ(hg(aaNm~ zC*HEjR$#X)6E5pf8bn<`sR_fO8QMe-gLXDbteYYAqO@!e;WV$zG;57@$8MNWm^GJ9 zvt(l1@nB%1jzxUiHlx&vyiB+eCj%3;tu{=NW~LQ{K{nPwnvQH*T_so842NORHdzoy zX;ZKFf|Pd|7_fTFW=3y}qPF~MWS-{IdaSz^GmEV(=1**jRH+`uX&SUbyQ~MMZ*_`J zV$*gnj*(4XkB2gie*Kx>KOJk6WWk1MXRkl=VqsB!c+5sNF`<6_voGiqctVGE%ZBpK zFtHmpu_)GD()p#B9Ck3L_;S(roxp@~R}>qEw)#R^d+-jpPZYmj9WG6u8+f6xhOo#0|UkL-~3d>G5>5<;1{eWOR6^?5mJc>f()Z=*M z#Hhrin-5b&db=02d%A59b3q7^IyTE}B5Sfn9&6hY#Wu=<#Ij;1NDUFH+hH&qk~oR& zBnH}G^2bh}Idx2@JsXD0E^`KkoEZ#>&{|TZK{pCE$d@Q%!qzAwLs^1k9ELWNMK*%V z-arx&xgBbjYsVohl3PvOAz3HcVcL?Y`49fBb{u6%9AdM0TMtI)?*jrYT z)~KtFdNNW+bCY7iS?CwvZTD=XO~IcyC9)Vs9kzK-Y4>jl^v>DfqIOym_PX zVg#QPZ+mc-m?#|@A(ffgD^tu%j_FxFc16ag|Iyg`no|VU%o7!JEPI-i6vh-;PdGWt z^F-#0OlH-w$OWb_e#!Lec$~CZVKytiZWVqa(x^S#m>nB4Y&%Z+C?oGzXeiGH31(j- z(s*EX$dXQHs!ye06eS`jVf9!Tx8P#O7!@9nGA31L?ADdYk0X3V0+ux@A6w>}*hzv= z!qJCz9*%ih=joQ<=bB9D62{vNqFtxsG_wO}s4NWXM9{IYVat$e1#j|Yw^yAc_22y3 z$W<_PGH64v7K9$v$&v$Ic%PEuB^LK(zu{Vp+1$<;(8exqmSMT4%A#R$HzlczGn$oz zMq&^&D&H;7c*(JE&cwBRs8}De!VHFTuy9G(qe`B6Q7np|Xo&RHv88G>EG;S3#I96I zXppkMMX2B+5?Q!8vN#?A6FZEP3}^bbqNyqcozKqE1A3^ec$j$|;=DJLC@v>M6#J)o95yj0f63!|dJrQnIXFQ3jGh%pk29**bq|$?x-?^+R zeU;O$&;Q&9=B-@kWLY{_>BTCAY?~S(#%j+P7853UrD62}YKVl=CC)xn)XrO#vr_1l z`|E6@&Xy^w&IWW0Goo_AC0(ji39>ODDchk*Qz|oyolW9R`Ef{lpw8tk)Q4g7b2hb^ z|68s2{+n78Am!<>koI7#&r7w`0TG23()*2@>U`N1yL3A5y5>BY)cK%0FzS3sfNGsg zGcHtQX3r7W%+O5(&PTGECkw|s8>3J{Mp(gBM?(*q_u`UWw7=TWm-eiX>~NIOm!i9@ z)0#CzMUfQ|XLB3ZnB;BBKqAX`vLZxAn&_TMq{Bq6#3i82NdcB_t*qNJrC)9qoW*K6 z19qfm->sYdk^%Lo-dEl1yUoHZ?9Z8LV68i+V9YIr6cz<&(n?%FJ~{&@W!n1 zwuX0T7RXZyJef*0NX9Gq#=y5zyQhc9#efweTzLx-JJKGPeeMrD-sg60f>{TUsV7qi z+*GSGOi2q!vaqEQbIxj|FrVLBiE-V)S(4|w$+DS}-qkU7;Xe3_Z3tT^h*m6L?0FFVbcZUvu$hoZmF3D?4s0Dy?};QHZOiF ztWU!d#peZOui%fyBYFB z)7-W#>49X_3f2`?OjjhWW~$6R^+qe@^sBlzS~~Uksbi%X_BHn|9idkz@*C^pA*u;u ztPDdFM31lsHVF(U3iD<5<*=J2bkhdVed(md+xF2^%zjgLG9#L-&{- zeBcr7KOT(qJqPu^N0u%&eCRkEJ>^x>4>tGhZ|+-Cr|m%7uon-eSHf|ePG8E1+38hH zpK1Cr8*9usy|QVV>e$#fm1KWGvR3UXeZ7 zbcfElzKnn0{oIE`r#m!=)13)fQH~)S-NSSz=}&it@NYVaWO4+D?dW1SC6O&gE?TLo zh(~v7h72Xf2X?{&%n`|!)P|c@>@nbZ+#&iYlYJtChY4$V6u$PXP`ID zmPunyU>53P!oCRy2J@tG-(*dFY@%&I*1fv7ad+d{kCoE!(~J*R`H4N2ukCwm$k1Yz|((`UoXgwrcgoVt^f>9ahV zJ~|?dPA3?6)9#_`!g!(oR_s_kNGXLMK-Cz&;#;w%TAP1kIK7f^0EA^b-T}nZOW~;g zYTU05B<$wr)%Q8e+^{|4Y`NvR#R+ES}Jf zNj9}l4t^3n!6C2`G z1utf{UT!3)>H$(?f;pc_0+a$dufAD^^ST7@LQc|@Cw$7~m7^1CTLTewj(FJsyp zDCVjJ8)ABX7c8T2Gmc#OFT=hc?Dl@PSgyzwE_X(?fC^I1gG^DnXuzje265MiOTE5} zvqbf4X*!X)qO{{nYI&5&ThUrTTyRSdKn|#$0p6OwB??aXGEutb;ks3+4VuNOI>$M$=xpa@sd$gGPT- z`QZW`2s;_qXtA{~M>+r0+fk?-GOSUi2@;wRYC_)9!j8lFU8IQYwx0FRw>(o2#Q_F$ci#w5^f z!XlR5+J#Zf3C!+AYOybU9EVDV|B7tMMo%Or`+DR|i@gxJE=QLH7I}GX3)A*p6G!vy z`tJqPv%Ry?B#@>Jq9jh;oSg8i(KyfVSCEumi;QCbP$*wdPB+eP>BIb=7hj=Ls(sA6GzL$C7;Xwu(X(7@g!caK812b{rv8* zpsycr8b>&eJ{QNmBWnrbI@9UL#&MFzU~&3EMAFmE`g$2T=kNK3hwh}HPuK3Tp)3v} z<|`=dK|3$W4x3+#T6E=eTUhEWDV|nK;`Qe#DfNAbXMwp+e#%tq^IXAOxa9LIR0M2viA-sER5f$|nR(MTGjHqN>y{R4O0% z{m(h`ve(y1I`Zs)XLjbC=RD8x_8;{PYcca6EsLG4BUI z5B?(f3b+LREqEOKCvXjX_dASCv>y4X@c{}*`pyc=l z$UpO4KJ?xXz@Gzu3|13*HE>fbRnz0Pg}n1%48Y!H2-Ffrr5F zfm-J>i#rT{43sLjz@GII7|D4TD7g;sq4C#2 zy>||joKJ!bWj+gj9L&HR{8Lcl-hPWQXTS>}sxp59YMj3WFM?kO_5Q6aQu5vnYWxnU z@$U!uXAbi5+u#`x)0^*rw}amU^_+y2+&6%l=e^)w@GemEJ?8NusOJYDBAREw{ov<7 z$?+E;rZHa!_1w2WjrVPE1il7tfX7g(c=?Cm$H2b^p9H@TJ_4@a>elx~Q1fAQUGqPn-unrt`!}*E>3 zKe-2#TpfRZ9n|xWfvC(p4laW!_$c@l@F@6Qa2@=}9yiZ3pzO2_YF+;Z{u1~dFadA+ zkTEZVGf+Hx--qEgcqe!n{2VC#{V#~A&21O~moXhsym}Mc#ykvu0F+%m18SV-K+XRp zP`vwHFbDq_yae8gQlW(T0(cO71q{Le1jWloKI+!@A}Id+7(4{tkJG*roP%rN7r-9) zkKiNVGUVf{8G`Qse;>RVd>LE;{~UZ9cq3~gJEv?Xzm;u%hEp8ZAuj2FX4XIT zeS`BNCnhw9I1g}ca_SKGPuOq9{IW-=WRHD(%7^ac{1to0`5G>|a2)4KzWjvlt_4Y4 zltDHOw&HYwFcZ9%!)W2xk1AunTFFS52kUy zoaK=np>U$~qA|h+JW{W$w;c?kVK__5?$T+d%%grbnMCOzLj0&7&WcF#GT<=FCt=!; zf{-DKGVH}kTy6((QOu&EJ&Rv(IGrYOKP=-cExN(xI4*dW7h`7cMP(QaXK7!*h8m~4 zw3!8?2sKMr5$eyQ0;!5%niWOdOQOBOB)k*_1#6N{`{OJ_Ha(tAHB9jO^Ituk1z}#s z!?0hz{`||8M)~1*lty`&1h4An*ea9S z8He*YlX9Fl4Yt#868D{+qu~&rf>W@=(>s`l$t==p#>kayFED+UCde6VXEQ5Ci@J6^ zRFMW-oXp`Vxh1kkX&L7cGY;Y+gvdcZiKkQiD~|?wNOWQF z3WWXAd(Ay|ct5OIp(EU6Y|(+uW_ zokzhU&0>`1WPuFGN>p&+gDYkTi!vIRBeSB+Ch_G6t7in9GL8zf9_E+$D8}|fJh3db zZnGZsW+Sui!k1b1+C`hSvsCxC#!(uCRm8F!7$GzwIkVy?3-9H%Bu)l z4c@)h`_hN^OHKP$UPc9JF%1=lY74Z6*eN+yVD`+WB^NN(v&dzsiet4=TI$&A0;{~) zg$$y2>0L(SrC}MFqp9Vnazv9G{M|-VRvVrw*_#C;8%bQ6V`c=BaBVMl-hzi8%kn-8 zsfEYfy^0QSo20mfbulHk(9KjA}(5uGKXj{2XM~h9l!??@8CIfT9ApgB-vI6 z{|bt2{9=Mynv7*0jRz6&w-@5vRix(TXxtv8aCe@a+0<%I#(hG11QL+V$tLPrFFK{H zDvi5(q+@HJdTgr<0@YR7K(BdAHQ6j85s@n!I#WgER5+8k)4I2}j)XSe``Evbg<9H& zFsLCU0qr^^By5LkpRKE`tQ8`C``u<~R8l?F5HM0HoWM&xGKVUd2**`6NFxl7fO#~{ z@)BdZdZ%kzl?LCfp(hk~Wpz7dOO->c4W(Zt zlazGoCQ0g?O0kAn%^4TA%^4})oMA~h3~3dI%{}W?jjg=*x-jEy5Wbn|tSn3CTSa0k zb#9TBq^y1&$WdYLa~rcyScW82`C5NzE!)>nu7I(hRyXEsa>s6KMIl7C~ zh~)}8TmRr*lZ<^q5{NI8l=ONmmbz%W_(*uB?nRMjCXtqMnMOZkCT$P_x2gu_FJf z*R z<~c2uU3ceb+Rp|Q)~msTJw`r@9AVO-3Y-+HK{~aU#lr^<2JY*_Y4E{^gZ&4Wp6ECZ zS!G>xOA7Aq?&}Pq`I5On(ai>>pHXM9AA)@)WFCY>+cYSKSwB=;_Pppkb@hlzH zV}!=vp$nl=Xs?7S2{T>NC}OLbB+CpQYGM_j?NN|qAPz!`02CAV3yjpk$zTbd*v1Fx{-nkA;=J%CJz}Z zAeSXE+maxU)k7kL_%0IKAv)7f>SH?Y%1r%;hxJ~voK4*d_nf91Fk_pMmuxP}GTUQ~ zhOT`(;&K@5@llL!06nFXG3_Kw$ADu>tUaw>(nd`cc;}qi=LS0&#X;OwHzT;>l{%_= z-to%yq})qu%|&dQ8CnC!fp0c7zj}6AuKH=E0C(NAoSGNJ)HcD~OhIh>PL9Ua=1;*o zt+&p;gsZgG@)tkE4xhoyuIUujLumJ{{91DwJMS`oF@tp2n&*nEXkRU^YfjE4ahg%K zTzSQuBIKxrvV;G2t52XebG;HEmF zk&SR(*7)l6Ew}hVj>m!s&xV(#Ru=3+dK_;e@5s7K-W4kkv26x5fTJ8I)DmewdD-N4 z{2tM%;#(Qo;1GKcvT0KbcO5TunGu|O6mW4mOlCC7R3%I@0$APaVpGP|EODBzB8vLK za_}sn7{5x0M#)aYMAIYTq!))`uicMVak;iYH#kWIP#28R@RjN@TXbjg1e7HkvVS3{ z7Q@*@+Ls^fYEfoX3yhYEHMfm6er60fQ-!tA41=0Vr0Rw-u68|z4RgeEN4jj96Qp@; zgYcEvhFHt@+xuslVrq?@ZRlg0Rg@ER6p*%ZM(e&-huUq7bxG5P-g(@InXTs*(?+=9 zu~tRacIO-qrj9A1ll%$H@l}E#{=o6576eP-Rv(boDrWq+$kbUuGbF{Wr&@=(fTB4OUb(U_} zKxNA#V_SchL;e5|hlGrcCfis(?~?A!d0LNEUV;(JOJTgD6aUK z*XB5U<~xgI8yF?(WOJ<8&*Qlz2bqFf#LaRR!{SA?HvxFTnk3B`{?W4i)odU}v^Es2 z%BG|l%i`ym>>-xa$x$px@McDiC<$y~LGQ2L7PY>*K;Kf6ezU2fBP*@q$x3(#ijqY#!s(2>kl^9$IL~S~<}*~D@yBkm{Dz~52%?OAUVX_D z#+dUl*&hA!!UFlLM;7m@qB_iWxz(lgRaDchB*pm(dSS0w{ci(A@r$YUel#v!`?8K2 zKB1YDz7|^Ktb%Ijwya7UWd6D?@UQ^fmF2WbO_=qXV!vKFjQ4u^0zg5nT{%q$}jPizd>z7wgTFKAv@hexdU@8 zS6xn53CfO@4xA*rIS!${UOr{kF3Z=*?Fy4|>#jgSb!Vf@E_;K6qDQqQkl10u0?40; zXO|(#^%qsi&JT7+xg*S0DW&O${50|KjYoykwj0WN=2<^lX|~FuH7oyAwE!(w6*Nk!*Ai`%GYVFHaW^%@NE>--ZW7h17LzH>h?O#Lsj=5 zV@PePBb5NKLOlXe-&gH&(V9gI0jy*%=JOoSu$@%i@|6q2R%Mh89#tje`kqZeCznBx zR2wK2G$aIDKH80u{$Q#WSe?r8C$&u%UuV;0_r*NuB2E?j+MUzW3T+i>TS2oP+NV?e L&oki1hM5sYVPVvo?mOM(R97`s)eK`u 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index fb807053f467c5def38fd4841a791cff9421cdd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11087 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 672f1924a1764d1ec427bd89fd77b269eeb862d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14926 zcmb`Od5|2{eaG8?30@l<1m=j1-G*@4nq3_nLLfk5#bKkvl0YUVwtHuLciYTNZ)Rq- zEJejSERG0Jh2VtXaLAM)N5xqQEfTtL5?35oQI#I@2UT&|ruf5^a+NEW|8SKnRr!2> z@AXX2>@0|KrquJD?tbt0e)sS9-oj57o%YRu&nVX?xNbN#2p$FRJ)JK;+s_DsPl7wZ z-vM6$2f(A?ZQwtFtHHBA6a+E25qtxD6+9o@#o!S97WfhH7EJK%4F{|z!F zIQ7Hs{!H*P?my}8*MeH-Zg3EM8e~fF1MpVxP4K!81i^(YQssX0nL+SD@b5wK@dJ>5 z!B6?pykCIlg1-V!1J69m;Ue&C?#~A`|4Q(;z#;G)@LKR9@blnJU;^F%{uOvL_%l#) zUXE~Uz^g#1avJ;?_=n&a_!PJe{52^0b(C;D_yG7N@KsQJE`k~Hc@ZeSmhmO}!=UDU z0TiG2fRGBl0$u~AU>$r36x|CK1;GaJE)Z1(-vLEuKe!b<0c!qv2q}Iq14X|CivHCg z|AOoJdK}yUV*236;DzANK#dc#;`?+^>zoZP1}_4&-se1S1vP#YgvH=%;8O5GP<(tB z#5BPPP~+YJMej{;9Q+Bm8N3yx$}gV*uL9@5d%&NAH-f|GIr(;hve%Emo57Fc6ry)8 zxB{F2*Ma*$jr$MqN^l5gm0#WiYJ3^gdMWrz{OymxJGlQk4+p^?g3`yYz^A}PA9w!v zGWZtvA0x=V%Di8IOSoT8aNQ1m9YmzypFutUF(^7`eah+m3Q+eqfFXD{coR4cUIHEh z8+3zh-dVd>~T#GKn2fz}@&|nyp-NyWV z1C;-N6BPYdKvWg{19&m`Z{S++f5E%KTP{Oh@ELG7_-hbV1UoJ#hQVh+R2W=yg|ov3 z@K3pa1Uwf#eF`JUpRW2$5bOnS0{<2K7f^Iw{48U@*TLoBPyPKlI2|DrEC1|MQTnm%Z<5p1oKLBdp9`N(v%b?czA5i?A zkI-6Y2-NeH;G5u=!6(6`1clc7KB)Qs1%4Y`b+z-$x51su1T^a&6(SPlW~Lr9uW-Q(|112MmSuJu1ePjcD zFt^3SM!R!gp95qA#c9ZeDy$~TPG@sT53+IZ2UP}N<-&yn!olo&Bba~gVYa6BlN%x(Nj9xi)dhE+bs$ap9)H zDO~a`eH8Qh5N^S+{c?GAE58Ye;AXC6TwA#GIi2ec`-Lxf{ESCjKDd`laq(sUYz-(s zFMe+0<||xZ)Wg+bC22InbS#`sYNP3NBdn#(u$hJnH>D#Ci=h=+~15|^84Jxpr$xKXahajh}Il6T#~YCUw)ZE<~D5>FQh zE)J&}Np0K_jVhJNXfm#clS#QbRgaBA!?7|FPrzKrkhWwaGvR1F7EM)}g9GbXvL2Vy zYBjEn#;_lkqp3zLejzxP)~ivi9ETAk8qH`VsU*#rFljWV;zn^5FK{$DSxL%KGf8WW z!Enn&(qJqT6ILIIn^8D6RV(XlBszlwTheemM$OVyjQZg*OdPCq*WFXZv5QPs6C*Ova*e^PTO_<{IV2ZE-EGN0soMhn@^?#}Z*B z-WFFhX0jfS#q}7$1_wg_308M_569BVDC(3g`#m2`qDne0!DcFPaX_Q%#u?xW34Ud; zrsE4nws7yrtf??UP8h6_3n5%?cK@KBj3+2AoQ!I*jMyZDx;HRUC34lc*|ZR_A-j!eV5$V9X)Nu?YYO`|ilsG5|Wp5w7G zVhW$aJG^^`+oH-;ENLd-t1{E&=~J}|e1)=cU#D~=|O2uBXfm1J^~_^QXF^@!{O@!QsKShqH8OvIJSVhgZp zL}*nfapbPpYb4{fWQ?$?H6b`M)x`EJLCj88;-(fEOYV0HlH+(ibZM@fR!BBpYchv| zQ$ZA!70>>K8&ytg&3alvXX$iUokD)+5J+JeBB^0GbE>Y@v_f!;t)pa7OB0mlc)=Oq zm8{^>2Y0LxHJb5gaLZJqnO2hrVyvE$aGFWn2!^BjeS9@0>`Q)PUTR@89FI(m2g5FX z1;bvuXtNzG`LpSXxE4lv#>GChII8C}yhBNXv3go<2a+vhGqGS?&ogXJd~l)p(ua>r zEqgMPQ9-RS87U35El?oQ%Q;qH_0-CeOBlmx?5b4mV{M}p)UntlRzBtF3FxKkHT$WlqCOT<^$m?18z zsHIb}g4>hPnEX2u5!`vE=Hd86kx0Wm`GYAdt-+m1nUo%bB;?@EPS&+3TBoWijk|uN zWW7(Dwkd-|HLn_InzvM^n#B|%YGucr>7wd%IMt+7c(%Bm2`%6I+}~A&3fjkEP(wrk z>boRPSWMTxTIW?+62g6PZbvjasS))Mc%(`=iI;w48?J(h2wYWzT8!agupUpQ^(Mx2 z{mx)e=rs6khOW}wHS?Rc)k)QtH|51Sar(bn=&KceOcr-MS`v4TwU{o4TpLNhDke3` zsavGduBkL@m^Iko(sr;xiVrp*QXLN|G>4sM7F8Wv`RH|N#@irzFVh(>1Dgs>Vxe?S zQP)y<^*K!N zD5OwRIx`q-?zHO`PMfWr_rVlwPR6TIu(^|GgDpf_WUeC0E=QoVh&CTE8)-F{EG+Yk zO;zMF$_iGGsg|MNBq+M*%fpCh$q>%S_5k)&Ff%7E`Hh zw~DT1Nikia^r6!}^PAIgbf3jiTLQLs!Pbd{7FoM0w?_}xlO^)seac>*KT3CumhM)- zr?r)qkxJE>lJ)90M^m-9c|QqJ<)O5$F`kT;$S;l3mULw}uyI3aQ@kzF#L_TzWo5W* z$+G38CD)dgt_YVdTY1&hpIx$i$&!IP3F*=nnTAFst*;DMSK|8`sJtGoi!1E9!y9;V zf7O1kSaCBsC8-Reog0~28=pdtr7dw(T^VkgVzaFA6V2viW987$M5^9;a5^4Q4>Xw8 z$A{3avSMRMVbvC;=dM0A)FHkytWOQByJOwjjvAH@E*Vhoj^~%Q%uFJhGRDwkB}!`7 zvpJ9I7<|=TTW&3_=!}zuY_>~lYvpv5etKoNVkBt}Y=n=fQlj~*HdcnUNxN;VT7G@# zey*xrx^&5^RZGLmE(`T@$){H>T^imLE(saU{f(=Z<*#m7b(MZzVZ&}%x+Hw?K{tgl zORi+jQsykXe&CBG=Y*#1jcGhe{a8M@d~n%7knPJ}&knbCWGAvCp}x3|FAjyRom|^n zd$PGOJ8oaCUD>PrJQ23GXS3O%>=-W(WV5ZEt;YuYQwp<#+0oYC!UU)uZtZ3GQ>?Tf zG6%SafLk2m#WzgN=2|;@ri+&&Ve1=WwY4kE4#38K@tV!%RQPcqM6wgC{urE|aC~NS zx<^`xc`VEhLtrN>Y=_uf_8KqdLcN8QUOnQJkR9k^_vDy*4whI~OrcI`xXn##7aD77 zc{9u0!@X}$T8p+k(^=?M;}Va_jtz#{-$MF?3@$^#_oIUS5+Iu`!I&($1J-c3Zy=Zy z`w)B_M)sFAHQV3Xle@((^y)qDIQ)uR9%1vtxt0z=Lhb@_#M`r27Gbemcm#cnXAkE* z;e@g_Y#)}=U)R#8;;HhV6uP&!RuzZj)*52wM(nnYeBZp1|p`M>#(tZ zB6~&5we}ReCnscSqA#K6d#Shf27TD+9hJQnUXh#d%J~yqlxMR=Mmx`5mc>!X9;jG^ z`AjySj?w`dMK=n`xjqA!+S-lW2j$SvGtH6r%$`I*zGHI@I}u9wqON1|KBdXfZri%= zCw72P8f2{L&Fsr&?!5(B!7a3xLuLLR<-Tq8Yc-;IQx9TrCN>`P@ z|InW)Bv(qWQXysOSs9T$r3|H_B|VA*e!=L|IT>F*Ok#!3L8oj5_~T>8Pf~ZxUN2z>>l_MAck{~S3uzi64+UD zCrzuO;?p9W3(!@`99IVvc`~ljqB)xB$^3J{@`pk#Q2U5wW|Hb~(RSf3c%Vf^my^wR zV#OQ=u6*fIap3tdu5o9S<(ef>N5Z+eR^qTm<~ipX zai)ChBhXTRkOw4>eFYWsG88QxBn|}Gw~_dms}$<4SDr-5+BGFU?A*PO8LG#h zOzX5DMJc@C3TsDJ5niZ~n6Sv)LS)~i)VO}*{VlMd7n?V2ht>HtZ6TGZYxScSRvuy! zJh%&nkQb-|$@?tHxp#e%l7({H-=*H7>asal>Pnont5!=aTUmZ6?n+29xGPCtOt5gF z1mXPiY)L0NF}(z{Y;SGtk0->DE^I8H=jyO| z+B|AA024BS$_K&LYgAvu$c}{~BAK)$@P9c(`@UzV#NB)lpY z9kW6$$+TIv776bAdJ(Mk@MFbF|KATbzjeRe&GBJIk# zO_8Z3rkPs3*C7*EJ)hV$74FDpk!j(*SCGA6;|gAj%{za#BCL!-rRrIAxF^A4aSrDJ zV#fL`^G#ws$i9WZ56K>|Oq&v9`|v>OGcLeR$avxnr!zdV-Ryhy%sO+?MyC_`EY>ZP zKSaD!|E*BbnON~yA=WX81@}DXazzVecCBP*IJs8Zy^Cme;slZ;)85M9*Hx(HzGaOZ zX-BCxcNhYNUb)jvU|V^z8M%u``4W20JHDRqDOSz}WcW>X&+|0eyN04yS!yQ-Mbdt^ zdCaj8;2^J*3$TFpeI(dd>EyR_uTu&997DOY2eowUnNX{5>v+@YJERF&fYUXSmh4Hu zoDgZ9NH`s#NaxEwgJpB@yzog!ZxHzwknZU()eBlzm^ZkxkV~?!z&@QiHgt=2F%LiD zla%Lznk+ki57(XfphH^klhmXdJPG>9XG8eux2>(6NY;)pOYXF0E`!1Ui*TWiT8UD* z+;(x+IrO?LQW{iZ`RJzu>0Ok~uuPt*S}t+xE6*KK>75=ZWTtzt0}&L9 z+MX6HnKvJ6_!~$2FUlD41%?*ulR5t3a3lYnP1F5_*{jX1rcHQzud|P}Us2VDT^KQD z+lm(kFRm?PQ3J-VYmuZt>n8GJ z51*-u-7NNWj_B&3SmAsOmdK4(EbMI5T4m)*MJAORmY$Yy(uRBqPoQKt@#gWv;Du6Y zNV3;-MRe{=#iN0Kw4P`Y@ImJ{8rY}E$Vq8&Y$+z0D=GS{8+#h7$x_-F7EU#s zNxL4hGWTX=+b?t-p4mZEcUI}{s1^FwTasb;-Lvy8bZFw!5|k@i@J=~*f8;{Dt|}1y zO6PbDul@OeZ14XtK%x=lCgXb0ECyfUH||9 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index abb13d0c9f52c9c8f11313254ce1c67bdfecf331..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11134 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index b561cb0c35b4e0c70c7b4ef1880c761704644811..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11310 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 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 6854bc43596c18cb4e47011398042712d740d16f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19778 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 Ij33Yb4+3(~3;+NC diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 55feb4f6526680422870861e259701158fd42477..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11767 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 GVEz~W!eBc9 diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell.mo b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 76566814dbd9a961656e18d6f8529c645663dd84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7854 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 rB^BI1iX#iU9slGl=9K959Ywntnsj { - 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; -}; - - -export const Applications = GObject.registerClass({ - GTypeName: 'Applications', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/applications.ui', GLib.UriFlags.NONE), - 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, 'active', - 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, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'enable-all', this._enable_all, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._customize.connect_to(this.preferences, 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/customize_row.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/customize_row.js deleted file mode 100644 index 0115966..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/customize_row.js +++ /dev/null @@ -1,163 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - - -/// 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(); -}; - -export const CustomizeRow = GObject.registerClass({ - GTypeName: 'CustomizeRow', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/customize-row.ui', GLib.UriFlags.NONE), - 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(settings, component_settings, color_and_noise = true) { - let s = component_settings.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_settings, '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( - 'active', this._color_row, 'visible', - GObject.BindingFlags.SYNC_CREATE - ); - color_and_noise.bind_property( - 'active', this._noise_amount_row, 'visible', - GObject.BindingFlags.SYNC_CREATE - ); - color_and_noise.bind_property( - 'active', this._noise_lightness_row, 'visible', - GObject.BindingFlags.SYNC_CREATE - ); - color_and_noise.bind_property( - 'active', 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.active; - 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; - } - - // 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) - settings.settings.bind( - 'color-and-noise', - this._color_row, 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - settings.settings.bind( - 'color-and-noise', - this._noise_amount_row, 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - settings.settings.bind( - 'color-and-noise', - this._noise_lightness_row, 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - }; -}); diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js deleted file mode 100644 index ef8d9ed..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js +++ /dev/null @@ -1,43 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Dash = GObject.registerClass({ - GTypeName: 'Dash', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/dash.ui', GLib.UriFlags.NONE), - 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, 'active', - 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, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._customize.connect_to(this.preferences, this.preferences.dash_to_dock, false); - } -}); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/general.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/general.js deleted file mode 100644 index 3067a2d..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/general.js +++ /dev/null @@ -1,49 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - -import { CustomizeRow } from './customize_row.js'; - - -export const General = GObject.registerClass({ - GTypeName: 'General', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/general.ui', GLib.UriFlags.NONE), - 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, preferences, preferences); - - this.preferences.settings.bind( - 'color-and-noise', this._color_and_noise, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.settings.bind( - 'hacks-level', this._hack_level, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.settings.bind( - 'debug', this._debug, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._reset.connect('clicked', _ => this.preferences.reset()); - } -}); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/menu.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/menu.js deleted file mode 100644 index 5ea2f3f..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/menu.js +++ /dev/null @@ -1,67 +0,0 @@ -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - - -export function addMenu(window) { - const builder = new Gtk.Builder(); - - // add a dummy page and remove it immediately, to access headerbar - builder.add_from_file(GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, '../ui/menu.ui', GLib.UriFlags.NONE))[0]); - let menu_util = builder.get_object('menu_util'); - window.add(menu_util); - try { - addMenuToHeader(window, builder); - } catch (error) { - // could not add menu... not so bad - } - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/other.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/other.js deleted file mode 100644 index d01f541..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/other.js +++ /dev/null @@ -1,49 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Other = GObject.registerClass({ - GTypeName: 'Other', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/other.ui', GLib.UriFlags.NONE), - 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, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._lockscreen_customize.connect_to(this.preferences, this.preferences.lockscreen); - - this.preferences.screenshot.settings.bind( - 'blur', this._screenshot_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._screenshot_customize.connect_to(this.preferences, this.preferences.screenshot); - - this.preferences.window_list.settings.bind( - 'blur', this._window_list_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._window_list_customize.connect_to( - this.preferences, this.preferences.window_list, false - ); - } -}); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/overview.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/overview.js deleted file mode 100644 index 2560e3b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/overview.js +++ /dev/null @@ -1,47 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Overview = GObject.registerClass({ - GTypeName: 'Overview', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/overview.ui', GLib.UriFlags.NONE), - 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, 'active', - 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, this.preferences.overview); - - this.preferences.appfolder.settings.bind( - 'blur', this._appfolder_blur, 'active', - 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, this.preferences.appfolder, false); - } -}); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js deleted file mode 100644 index 6d9f72b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js +++ /dev/null @@ -1,65 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Panel = GObject.registerClass({ - GTypeName: 'Panel', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/panel.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'blur', - 'customize', - 'static_blur', - 'unblur_in_overview', - 'override_background', - 'style_panel', - 'override_background_dynamically', - 'hidetopbar_compatibility', - 'dtp_blur_original_panel' - ], -}, class Panel extends Adw.PreferencesPage { - constructor(preferences) { - super({}); - - this.preferences = preferences; - - this.preferences.panel.settings.bind( - 'blur', this._blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'static-blur', this._static_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'unblur-in-overview', this._unblur_in_overview, 'active', - 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, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._customize.connect_to(this.preferences, this.preferences.panel, this._static_blur); - - this.preferences.hidetopbar.settings.bind( - 'compatibility', this._hidetopbar_compatibility, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_panel.settings.bind( - 'blur-original-panel', this._dtp_blur_original_panel, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - } -}); \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js deleted file mode 100644 index c9786c9..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js +++ /dev/null @@ -1,109 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - -import { pick, on_picking, on_picked } from '../dbus/client.js'; - - - -export const WindowRow = GObject.registerClass({ - GTypeName: 'WindowRow', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/window-row.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'window_picker', - 'window_class', - 'picking_failure_toast' - ], -}, 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') { - console.warn("Can't pick window from here"); - return; - } - this._window_class.buffer.text = wm_class; - } - }); - - pick(); - } -}); diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js deleted file mode 100644 index df622ed..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js +++ /dev/null @@ -1,41 +0,0 @@ -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { Settings } from './conveniences/settings.js'; -import { Keys } from './conveniences/keys.js'; - -import { addMenu } from './preferences/menu.js'; -import { General } from './preferences/general.js'; -import { Panel } from './preferences/panel.js'; -import { Overview } from './preferences/overview.js'; -import { Dash } from './preferences/dash.js'; -import { Applications } from './preferences/applications.js'; -import { Other } from './preferences/other.js'; - - -export default class BlurMyShellPreferences extends ExtensionPreferences { - constructor(metadata) { - super(metadata); - - // load the icon theme - let iconPath = this.dir.get_child("icons").get_path(); - let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - iconTheme.add_search_path(iconPath); - } - - fillPreferencesWindow(window) { - addMenu(window); - - const preferences = new Settings(Keys, this.getSettings()); - - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled deleted file mode 100644 index c5aa01a980b3f4ba7164801abb4ec56fc8dce54f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8160 zcmds+e{5A}9md}}y1{^f9bnmDGPA|oxZ8GsOWlU63DZttHvS-uKbD=_d+j~p_TFpn zZK3-i{evcr62%F#DvgcPjVLBnF=CucNnkdaBwgZSjWaSu!(XNvrWnlh`Mmdj?+>JS z%3o$Dd3c`tzsS%UnWixe?=#6QGBU>tWYQO=l}ja;&e}{?5Pw1g z#Qjf+kFR%bu<_wz#LwK~+}(=1TXmlsoV(P1X&>>AZ**?6;$z~Yw>g&^=xgoE=K52u zg>)*DX-(}drm}@Fmo2m=GJ^y0{^5A(Kk`8~l~D&87CmC!!8`yBtK%BX1@mCAxzLcg zi9NigyT4FP~aM9Q}61^Ws5a=o6n@O&r~*_=tE+D6HGQg*bY-;^X2; z!NwiUxWlu;_RZT?(H>1dbK(XCPT%q6=ZK@56mJ%96kdDy+ug*`s}ye+-!Du*`MKrH zE1G_~#E%PKf9}u|BCnSyKB6C^!dO223~}@_#Se-P3oqRDDyMmUqvDhLaZK2}Vc$Q9 zqint77?g(sWE-2xtF zZqRu6QE^7VtHjZGH7_0%@Fa0Go*WS$5XeE|X!;))PYUERaWuI+C4OEY*NCHOKO_Dt zx?B^{u%=fy__yht2P z|0l$!gtng?=p&BC({tkA36=wBJa=BaRtpbaq&=GWChP@|vCh{&OB~I8o)w=LUVr+T9}!3MTo=V{now#1 zaWv!BDc&J8HQe(WaWwt(h z@E2Ag2k^dLg(`l;Yr1`h@9MHzza!sI^+erJGAN|u#auk8I$L_M$ox1fT5Wx`@c-}EftrFAeSOl!7E@TPt}IljRQJ+)Cn)Cfi9nMZ`T46S>4t1+ zUc~u!iq5tbmw}0V{qn0wpi`y9jEo~RfuO&L#4N8a*g+^Jz+MP+Y`@(g`ziN7_2_%XruL}Z z`*HCE@$y~?&HWq|e_yb@6578Dh))TLuk8F8{h(<-D`vl)%LlzSvwznAlWz-^L-Hh* z4HDYyXiwxDUvWRgy2U!B*9t#xysK%c_v;ouWqvuBb1k1Pkx|~0-2`=XXM*f*y&=Sc zLd#;xdF4HEp-k8PTTXDD=y_4=VKT#Se@gooWIT7-4y=A(ReW9b!v=0?ckdK{6^z`m~SlXr>Dd}7R<9~ zJUcDEgf8a_nq2u8tQV2ekZ92lvq7e2UwrNBdfm-40bDTpv)8Qyi{C5qZOP}Vcv!H# zBAVPD6CV<6uZSjx$HfzZ?G@4Foo^9 z4`}9LgSbPmy&{^N?-KKE%yJ;Q|7!-2(Z5Q5z3KOft>#7Eiy3bhqlVc*{@7YZ-r8D5 zKHEBG%zUExM#+4-w>j4$F#p8S%zuY?yMVulqw!alc&A|biKd?(@lyi6qdgkmO^S~R z_?I{u|4xg4De!%dIGXQ!XT^UK8otoiL>x{0qS)yhD&N_NquCFw7OxfX9dR_i+a$hI z;Cmf$H1(xJyiFhvh@-jxE^#+nUgi5C8ehYF!;QQqM0me1RdUs9OA1{ndS29e!LJK- zJDu8n&O#}}ld-N|`BR?mtMqZP_CkIgD1CRVd^+>p`1)G+5k%)-;lrkHSM$Nf_6K;E zHHU-sh4qHDoHYmkvKHZId>wh+seMP*lhUspmMfMoT-(04n5X$pk0++Z7X_=mXuP{r z-|p84R(sLpMzeUMV6_)b4#dP;1*^Si`tKBX308a2_IdHw&}EOJ@#qop z3BhVFnjDxB^LK_Cn=Qg;)j_;k`Nc$-VToFezSDoSq1)EzmbK50O3wVn5Xgsx7ykEd0#L@JBQ2bK?PZ3AssTuLF1oJqW z_GiWG^tYyE7asgI?a{pR$HeUd-Y1U6`<>z)0^TQ%#{1o3{&r<4ZuwnT8q{9HmuS(y zjF07@RMaZBG+O%i%^fREkDc?WJjrBvTx00Q`w?k6?vxWzUB&l5~EU_M0qnjtl_&*eVEe;j!9|KEodPh7Q3*VXCr`W^ - - - - - - 30 - Global sigma (gaussian blur radius) to use - - - - 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, 3 contrasted) - - - - 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 - - - - - - - - true - Boolean, whether to blur the original panel (if option selected) with Dash to Panel - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css deleted file mode 100644 index 91cfb1f..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css +++ /dev/null @@ -1,334 +0,0 @@ -/*** PANEL ***/ - -/* -* `.transparent-panel` -*/ -#panel.transparent-panel { - background: transparent; - transition-duration: 500ms; -} - -/* -* `.dark-panel` -*/ -#panel.dark-panel { - background-color: rgba(100, 100, 100, 0.35); - box-shadow: none; - transition-duration: 500ms; -} - -/* -* `.light-panel` -*/ -#panel.light-panel { - background-color: rgba(200, 200, 200, 0.2); - box-shadow: none; - transition-duration: 500ms; -} - -/* -* `.contrasted-panel` -*/ -#panel.contrasted-panel { - background-color: transparent; - box-shadow: none; - transition-duration: 500ms; -} - -.contrasted-panel .panel-button, -.contrasted-panel .clock, -.contrasted-panel .clock-display StIcon { - color: #ffffff; - border-radius: 14px; - border: 3px solid transparent; - background-color: rgba(0, 0, 0, 0.8); - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03); -} - - -.contrasted-panel .clock-display StIcon { - padding: 8px; - margin: 0; -} - -.contrasted-panel .panel-button:hover, -.contrasted-panel .panel-button:hover .clock { - color: #ffffff; - background-color: rgba(0, 0, 0, 0.8); -} - -.contrasted-panel .clock-display { - background-color: transparent !important; - box-shadow: none !important; - border: none !important; -} - -.contrasted-panel .clock { - margin: 0 !important; -} - - -/*** 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 .workspace-thumbnail { - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(100, 100, 100, 0.35); -} - -.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 { - border: none; - box-shadow: none; -} - -.overview-components-transparent .search-section-content, -.overview-components-transparent .app-folder .overview-icon { - background-color: rgba(0, 0, 0, 0); -} - -/* 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 .workspace-thumbnail { - background-color: rgba(200, 200, 200, 0.2); -} - -.overview-components-light .search-entry { - color: white; - background-color: rgba(200, 200, 200, 0.2); - 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 { - border: none; - box-shadow: none; -} - -.overview-components-light .search-section-content, -.overview-components-light .app-folder .overview-icon { - background-color: rgba(200, 200, 200, 0.2); -} - -/* 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 .workspace-thumbnail { - background-color: rgba(100, 100, 100, 0.35); -} - -.overview-components-dark .search-entry { - color: white; - background-color: rgba(100, 100, 100, 0.35); - 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 { - border: none; - box-shadow: none; -} - -.overview-components-dark .search-section-content, -.overview-components-dark .app-folder .overview-icon { - background-color: rgba(100, 100, 100, 0.35); -} - -/* 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); - border: none; - box-shadow: none; -} - -.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); - border: none; - box-shadow: none; -} - -.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); - border: none; - box-shadow: none; -} - -.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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui deleted file mode 100644 index 0b4b83c..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - 25 - 255 - 1 - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/customize-row.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/customize-row.ui deleted file mode 100644 index 313bc48..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/customize-row.ui +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui deleted file mode 100644 index 5eac21b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - Transparent - Light - Dark - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/general.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/general.ui deleted file mode 100644 index 73c6b29..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/general.ui +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/menu.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/menu.ui deleted file mode 100644 index e7b9210..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/menu.ui +++ /dev/null @@ -1,37 +0,0 @@ - - - -
- - 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/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/other.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/other.ui deleted file mode 100644 index d1d24f8..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/other.ui +++ /dev/null @@ -1,62 +0,0 @@ - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/overview.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/overview.ui deleted file mode 100644 index 191c70b..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/overview.ui +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - Do not style - Light - Dark - Transparent - - - - - - Do not style - Transparent - Light - Dark - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui deleted file mode 100644 index 41d9cd1..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - Transparent - Light - Dark - Contrasted - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui b/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui deleted file mode 100644 index c4d8201..0000000 --- a/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - Could not pick window, make sure that the extension is enabled. - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/extension.js b/.local/share/gnome-shell/extensions/caffeine@patapon.info/extension.js deleted file mode 100644 index 3b289d3..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/extension.js +++ /dev/null @@ -1,1128 +0,0 @@ -/* -*- mode: js2 - indent-tabs-mode: nil - js2-basic-offset: 4 -*- */ -/* jshint multistr:true */ -/* jshint esnext:true */ -/* exported CaffeineExtension */ -/** - * 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 . - **/ - -'use strict'; - -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; - -import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as QuickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js'; -const QuickSettingsMenu = Main.panel.statusArea.quickSettings; - -const INHIBIT_APPS_KEY = 'inhibit-apps'; -const SHOW_INDICATOR_KEY = 'show-indicator'; -const SHOW_NOTIFICATIONS_KEY = 'show-notifications'; -const SHOW_TIMER_KEY = 'show-timer'; -const DURATION_TIMER_INDEX = 'duration-timer'; -const TOGGLE_STATE_KEY = 'toggle-state'; -const USER_ENABLED_KEY = 'user-enabled'; -const RESTORE_KEY = 'restore-state'; -const FULLSCREEN_KEY = 'enable-fullscreen'; -const NIGHT_LIGHT_KEY = 'nightlight-control'; -const TOGGLE_SHORTCUT = 'toggle-shortcut'; -const TIMER_KEY = 'countdown-timer'; -const SCREEN_BLANK = 'screen-blank'; -const TRIGGER_APPS_MODE = 'trigger-apps-mode'; -const INDICATOR_POSITION = 'indicator-position'; -const INDICATOR_INDEX = 'indicator-position-index'; -const INDICATOR_POS_MAX = 'indicator-position-max'; - -const ColorInterface = ' \ - \ - \ - \ - \ - '; - -const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface); - -const DBusSessionManagerIface = '\ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ -'; - -const DBusSessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(DBusSessionManagerIface); - -const DBusSessionManagerInhibitorIface = '\ - \ - \ - \ - \ - \ -'; - -const DBusSessionManagerInhibitorProxy = Gio.DBusProxy.makeProxyWrapper(DBusSessionManagerInhibitorIface); - -const DisabledIcon = 'my-caffeine-off-symbolic'; -const EnabledIcon = 'my-caffeine-on-symbolic'; -const TimerMenuIcon = 'stopwatch-symbolic'; - -const ControlContext = { - NEVER: 0, - ALWAYS: 1, - FOR_APPS: 2 -}; - -const ShowIndicator = { - ONLY_ACTIVE: 0, - ALWAYS: 1, - NEVER: 2 -}; - -const AppsTrigger = { - ON_RUNNING: 0, - ON_FOCUS: 1, - ON_ACTIVE_WORKSPACE: 2 -}; - -const TIMERS = [ - [5, 10, 15, 20, 30, 'caffeine-short-timer-symbolic'], - [10, 20, 30, 40, 50, 'caffeine-medium-timer-symbolic'], - [30, 45, 60, 75, 80, 'caffeine-long-timer-symbolic'], - [0, 0, 0, 0, 0, 'caffeine-infinite-timer-symbolic'] -]; - -const CaffeineToggle = GObject.registerClass( -class CaffeineToggle extends QuickSettings.QuickMenuToggle { - _init(settings, path) { - super._init({ - 'title': _('Caffeine'), - toggleMode: true - }); - - this._settings = settings; - this._path = path; - - // Icons - this.finalTimerMenuIcon = TimerMenuIcon; - let iconTheme = new St.IconTheme(); - if (!iconTheme.has_icon(TimerMenuIcon)) { - this.finalTimerMenuIcon = - Gio.icon_new_for_string(`${this._path}/icons/${TimerMenuIcon}.svg`); - } - this._iconActivated = Gio.icon_new_for_string(`${this._path}/icons/${EnabledIcon}.svg`); - this._iconDeactivated = Gio.icon_new_for_string(`${this._path}/icons/${DisabledIcon}.svg`); - this._iconName(); - - // Menu - this.menu.setHeader(this.finalTimerMenuIcon, _('Caffeine Timer'), null); - - // Add elements - this._itemsSection = new PopupMenu.PopupMenuSection(); - this.menu.addMenuItem(this._itemsSection); - - // Init Timers - this._timerItems = new Map(); - this._syncTimers(false); - - // Bind signals - this._settings.bind(`${TOGGLE_STATE_KEY}`, - this, 'checked', - Gio.SettingsBindFlags.DEFAULT); - this._settings.connect(`changed::${TOGGLE_STATE_KEY}`, () => { - this._iconName(); - }); - this._settings.connect(`changed::${TIMER_KEY}`, () => { - this._sync(); - }); - this._settings.connect(`changed::${DURATION_TIMER_INDEX}`, () => { - this._syncTimers(true); - }); - this.connect('destroy', () => { - this._iconActivated = null; - this._iconDeactivated = null; - this.gicon = null; - }); - } - - _syncTimers(resetDefault) { - this._itemsSection.removeAll(); - this._timerItems.clear(); - const durationIndex = this._settings.get_int(DURATION_TIMER_INDEX); - - for (const timer of TIMERS) { - let label = null; - if (timer[0] === 0) { - label = _('Infinite'); - } else { - label = parseInt(timer[durationIndex]) + _(' minutes'); - } - if (!label) { - continue; - } - const icon = Gio.icon_new_for_string(`${this._path}/icons/${timer[5]}.svg`); - const item = new PopupMenu.PopupImageMenuItem(label, icon); - item.connect('activate', () => { - this._checkTimer(timer[durationIndex]); - }); - this._timerItems.set(timer[durationIndex], item); - this._itemsSection.addMenuItem(item); - } - this.menuEnabled = TIMERS.length > 2; - - // Select active duration - if (resetDefault && this._settings.get_int(TIMER_KEY) !== 0) { - // Set default duration to 0 - this._settings.set_int(TIMER_KEY, 0); - } else { - this._sync(); - } - } - - _sync() { - const activeTimerId = this._settings.get_int(TIMER_KEY); - for (const [timerId, item] of this._timerItems) { - item.setOrnament(timerId === activeTimerId - ? PopupMenu.Ornament.CHECK - : PopupMenu.Ornament.NONE); - } - } - - _checkTimer(timerId) { - this._settings.set_int(TIMER_KEY, timerId); - this._settings.set_boolean(TOGGLE_STATE_KEY, true); - } - - _iconName() { - if (this._settings.get_boolean(TOGGLE_STATE_KEY)) { - this.gicon = this._iconActivated; - } else { - this.gicon = this._iconDeactivated; - } - } -}); - -const Caffeine = GObject.registerClass( -class Caffeine extends QuickSettings.SystemIndicator { - _init(settings, path, name) { - super._init(); - - this._indicator = this._addIndicator(); - this._settings = settings; - this._name = name; - - // D-bus - this._proxy = new ColorProxy( - Gio.DBus.session, - 'org.gnome.SettingsDaemon.Color', - '/org/gnome/SettingsDaemon/Color', - (proxy, error) => { - if (error) { - log(error.message); - } - } - ); - this._sessionManager = new DBusSessionManagerProxy(Gio.DBus.session, - 'org.gnome.SessionManager', - '/org/gnome/SessionManager'); - - // From auto-move-windows@gnome-shell-extensions.gcampax.github.com - this._appSystem = Shell.AppSystem.get_default(); - this._activeWorkspace = null; - - // Init Apps Signals Id - this._appStateChangedSignalId = 0; - this._appDisplayChangedSignalId = 0; - this._appWorkspaceChangedSignalId = 0; - this._appAddWindowSignalId = 0; - this._appRemoveWindowSignalId = 0; - - // ("screen" in global) is false on 3.28, although global.screen exists - if (typeof global.screen !== 'undefined') { - this._screen = global.screen; - this._display = this._screen.get_display(); - } else { - this._screen = global.display; - this._display = this._screen; - } - - // Add indicator label for the timer - this._timerLabel = new St.Label({ - y_expand: true, - y_align: Clutter.ActorAlign.CENTER - }); - this._timerLabel.visible = false; - this.add_child(this._timerLabel); - - // Icons - this._iconActivated = Gio.icon_new_for_string(`${path}/icons/${EnabledIcon}.svg`); - this._iconDeactivated = Gio.icon_new_for_string(`${path}/icons/${DisabledIcon}.svg`); - this._indicator.gicon = this._iconDeactivated; - - // Manage night light - this._nightLight = false; - - /* Inhibited flag value - * - 4: Inhibit suspending the session or computer - * - 12: Inhibit the session being marked as idle - */ - this.inhibitFlags = 12; - - // Caffeine state - this._state = false; - this._userState = false; - - // Store the inhibition requests until processed - this._inhibitionAddedFifo = []; - this._inhibitionRemovedFifo = []; - - // Init Timers - this._timeOut = null; - this._timePrint = null; - this._timerEnable = false; - this._timeFullscreen = null; - this._timeWorkspaceAdd = null; - this._timeWorkspaceRemove = null; - this._timeAppUnblock = null; - - // Show icon - this._manageShowIndicator(); - - // Init app list - this._appConfigs = []; - this._appInhibitedData = new Map(); - this._updateAppConfigs(); - - // Enable caffeine when fullscreen app is running - if (this._settings.get_boolean(FULLSCREEN_KEY)) { - this._inFullscreenId = this._screen.connect('in-fullscreen-changed', this.toggleFullscreen.bind(this)); - this.toggleFullscreen(); - } - - // QuickSettings - this._caffeineToggle = new CaffeineToggle(this._settings, path); - this.quickSettingsItems.push(this._caffeineToggle); - this._updateTimerSubtitle(); - - // Init settings keys and restore user state - this._settings.reset(TOGGLE_STATE_KEY); - if (this._settings.get_boolean(USER_ENABLED_KEY) && this._settings.get_boolean(RESTORE_KEY)) { - this.toggleState(); - } else { - // reset user state - this._settings.reset(USER_ENABLED_KEY); - } - - // Bind signals - this._inhibitorAddedId = this._sessionManager.connectSignal( - 'InhibitorAdded', this._inhibitorAdded.bind(this)); - this._inhibitorRemovedId = this._sessionManager.connectSignal( - 'InhibitorRemoved', this._inhibitorRemoved.bind(this)); - this.inhibitId = this._settings.connect(`changed::${INHIBIT_APPS_KEY}`, - this._updateAppConfigs.bind(this)); - this.stateId = this._settings.connect(`changed::${TOGGLE_STATE_KEY}`, - this._updateMainState.bind(this)); - this.timerId = this._settings.connect(`changed::${TIMER_KEY}`, - this._startTimer.bind(this)); - this.showTimerId = this._settings.connect(`changed::${SHOW_TIMER_KEY}`, - this._showIndicatorLabel.bind(this)); - this.indicatorId = this._settings.connect(`changed::${INDICATOR_POSITION}`, - this._updateIndicatorPosition.bind(this)); - this.showIndicatorId = this._settings.connect(`changed::${SHOW_INDICATOR_KEY}`, () => { - this._manageShowIndicator(); - this._showIndicatorLabel(); - }); - this.triggerId = this._settings.connect(`changed::${TRIGGER_APPS_MODE}`, () => { - this._resetAppSignalId(); - this._updateAppEventMode(); - }); - - // Change user state on icon scroll event - this._indicator.reactive = true; - this._indicator.connect('scroll-event', - (actor, event) => this._handleScrollEvent(event)); - - // Init position and index of indicator icon - this.indicatorPosition = this._settings.get_int(INDICATOR_POSITION); - this.indicatorIndex = this._settings.get_int(INDICATOR_INDEX); - this.lastIndicatorPosition = this.indicatorPosition; - - // Add indicator and toggle - QuickSettingsMenu.addExternalIndicator(this); - QuickSettingsMenu._indicators.remove_actor(this); - QuickSettingsMenu._indicators.insert_child_at_index(this, this.indicatorIndex); - - this._updateLastIndicatorPosition(); - } - - get inFullscreen() { - let nbMonitors = this._screen.get_n_monitors(); - let inFullscreen = false; - for (let i = 0; i < nbMonitors; i++) { - if (this._screen.get_monitor_in_fullscreen(i)) { - inFullscreen = true; - break; - } - } - return inFullscreen; - } - - toggleFullscreen() { - /* Reset previous FullScreen delay - * This prevent multiple inhibitors to be created in toggleFullscreen() - * if a previous timer is still running. - */ - if (this._timeFullscreen !== null) { - GLib.Source.remove(this._timeFullscreen); - this._timeFullscreen = null; - } - - this._manageScreenBlankState(false); - - // Add 2 second delay before adding inhibitor - this._timeFullscreen = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 2, () => { - if (this.inFullscreen && !this._appInhibitedData.has('fullscreen')) { - this.addInhibit('fullscreen'); - this._manageNightLight(false, false); - } - - this._timeFullscreen = null; - return GLib.SOURCE_REMOVE; - }); - - if (!this.inFullscreen && this._appInhibitedData.has('fullscreen')) { - this.removeInhibit('fullscreen'); - this._manageNightLight(true, false); - } - } - - toggleState() { - this._manageScreenBlankState(false); - if (this._state) { - this._removeTimer(); - this._appInhibitedData.forEach((data, appId) => - this.removeInhibit(appId) - ); - this._manageNightLight(true, false); - } else { - this.addInhibit('user'); - this._manageNightLight(false, false); - - // Enable timer when duration isn't null - if (this._settings.get_int(TIMER_KEY) !== 0 && !this._timerEnable) { - this._startTimer(); - } - } - } - - addInhibit(appId) { - this._sessionManager.InhibitRemote(appId, - 0, 'Inhibit by %s'.format(this._name), this.inhibitFlags, - (cookie) => { - this._inhibitionAddedFifo.push(appId); - // Init app data - let data = { - cookie, - isToggled: true, - isInhibited: false, - object: '' - }; - this._appInhibitedData.set(appId, data); - } - ); - } - - removeInhibit(appId) { - let appData = this._appInhibitedData.get(appId); - if (appData && appData.isInhibited) { - this._inhibitionRemovedFifo.push(appId); - this._sessionManager.UninhibitRemote(appData.cookie); - appData.isToggled = false; - this._appInhibitedData.set(appId, appData); - } - } - - _updateLastIndicatorPosition() { - let pos = -1; - let nbItems = QuickSettingsMenu._indicators.get_n_children(); - let targetIndicator = null; - - // Count only the visible item in indicator bar - for (let i = 0; i < nbItems; i++) { - targetIndicator = QuickSettingsMenu._indicators.get_child_at_index(i); - if (targetIndicator.is_visible()) { - pos += 1; - } - } - this._settings.set_int(INDICATOR_POS_MAX, pos); - } - - _incrementIndicatorPosIndex() { - if (this.lastIndicatorPosition < this.indicatorPosition) { - this.indicatorIndex += 1; - } else { - this.indicatorIndex -= 1; - } - } - - _updateIndicatorPosition() { - this._updateLastIndicatorPosition(); - const newPosition = this._settings.get_int(INDICATOR_POSITION); - - if (this.indicatorPosition !== newPosition) { - this.indicatorPosition = newPosition; - this._incrementIndicatorPosIndex(); - - // Skip invisible indicator - let targetIndicator = - QuickSettingsMenu._indicators.get_child_at_index(this.indicatorIndex); - let maxIndex = QuickSettingsMenu._indicators.get_n_children(); - while (this.indicatorIndex < maxIndex && !targetIndicator.is_visible() && this.indicatorIndex > -1) { - this._incrementIndicatorPosIndex(); - targetIndicator = - QuickSettingsMenu._indicators.get_child_at_index(this.indicatorIndex); - } - - // Always reset index to 0 on position 0 - if (this.indicatorPosition === 0) { - this.indicatorIndex = 0; - } - - // Update last position - this.lastIndicatorPosition = newPosition; - - // Update indicator index - QuickSettingsMenu._indicators.remove_actor(this); - QuickSettingsMenu._indicators.insert_child_at_index(this, this.indicatorIndex); - this._settings.set_int(INDICATOR_INDEX, this.indicatorIndex); - } - } - - _showIndicatorLabel() { - if (this._settings.get_boolean(SHOW_TIMER_KEY) && - (this._settings.get_enum(SHOW_INDICATOR_KEY) !== ShowIndicator.NEVER) && - this._timerEnable) { - this._timerLabel.visible = true; - } else { - this._timerLabel.visible = false; - } - } - - _startTimer() { - // Reset timer - this._removeTimer(); - this._timerEnable = true; - - // Get duration - let timerDelay = this._settings.get_int(TIMER_KEY) * 60; - - // Execute Timer only if duration isn't set on infinite time - if (timerDelay !== 0) { - let secondLeft = timerDelay; - this._showIndicatorLabel(); - this._printTimer(secondLeft); - this._timePrint = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => { - secondLeft -= 1; - this._printTimer(secondLeft); - return GLib.SOURCE_CONTINUE; - }); - - this._timeOut = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timerDelay * 1000, () => { - // Disable Caffeine when timer ended - this._removeTimer(); - this._settings.set_boolean(TOGGLE_STATE_KEY, false); - return GLib.SOURCE_REMOVE; - }); - } - } - - _printTimer(second) { - const min = Math.floor(second / 60); - const minS = Math.floor(second % 60).toLocaleString('en-US', { - minimumIntegerDigits: 2, - useGrouping: false - }); - // Print Timer in system Indicator and Toggle menu subLabel - this._updateLabelTimer(min + ':' + minS); - } - - _removeTimer() { - // End timer - this._timerEnable = false; - - // Flush and hide timer label - this._updateLabelTimer(null); - this._timerLabel.visible = false; - - // Remove timer - if ((this._timeOut !== null) || (this._timePrint !== null)) { - GLib.Source.remove(this._timeOut); - GLib.Source.remove(this._timePrint); - this._timeOut = null; - this._timePrint = null; - } - } - - _updateLabelTimer(text) { - this._timerLabel.text = text; - this._caffeineToggle.menu.setHeader(this._caffeineToggle.finalTimerMenuIcon, _('Caffeine Timer'), text); - this._caffeineToggle.subtitle = text; - } - - _handleScrollEvent(event) { - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - if (!this._state) { - // User state on - UP - this._settings.set_boolean(TOGGLE_STATE_KEY, true); - } - break; - case Clutter.ScrollDirection.DOWN: - if (this._state) { - // Stop timer - this._removeTimer(); - // User state off - DOWN - this._settings.set_boolean(TOGGLE_STATE_KEY, false); - } - break; - } - } - - _inhibitorAdded(proxy, sender, [object]) { - this._sessionManager.GetInhibitorsRemote(([inhibitors]) => { - // Get the first added request - let requestedId = this._inhibitionAddedFifo.shift(); - - for (let i of inhibitors) { - let inhibitor = new DBusSessionManagerInhibitorProxy(Gio.DBus.session, - 'org.gnome.SessionManager', - i); - inhibitor.GetAppIdRemote((appId) => { - appId = String(appId); - let appData = this._appInhibitedData.get(appId); - if (appId !== '' && requestedId === appId && appData) { - appData.isInhibited = true; - appData.object = object; - this._appInhibitedData.set(appId, appData); - - if (appId === 'user') { - this._saveUserState(true); - } else { - this._updateAppSubtitle(appId); - } - - // Update state - if (this._state === false) { - this._saveMainState(true); - // Indicator icon - this._manageShowIndicator(); - this._indicator.gicon = this._iconActivated; - - // Shell OSD notifications - if (this._settings.get_boolean(SHOW_NOTIFICATIONS_KEY) && !this.inFullscreen) { - this._sendOSDNotification(true); - } - } - } - }); - } - }); - } - - /* eslint-disable no-unused-vars */ - _inhibitorRemoved(proxy, sender, [object]) { - /* eslint-enable no-unused-vars */ - // Get the first removed request - let appId = this._inhibitionRemovedFifo.shift(); - - if (appId) { - let appData = this._appInhibitedData.get(appId); - if (appData) { - // Remove app from list - this._appInhibitedData.delete(appId); - - if (appId === 'user') { - this._saveUserState(false); - } else { - this._updateAppSubtitle(null); - } - - // Update state - if (this._appInhibitedData.size === 0) { - this._saveMainState(false); - - // Indicator icon - this._manageShowIndicator(); - this._indicator.gicon = this._iconDeactivated; - - // Shell OSD notifications - if (this._settings.get_boolean(SHOW_NOTIFICATIONS_KEY)) { - this._sendOSDNotification(false); - } - } - } - } - } - - _isToggleInhibited(appId) { - let appData = this._appInhibitedData.get(appId); - if (appData && appData.isToggled) { - return true; - } else { - return false; - } - } - - _manageShowIndicator() { - if (this._state) { - this._indicator.visible = this._settings.get_enum(SHOW_INDICATOR_KEY) !== ShowIndicator.NEVER; - } else { - this._indicator.visible = this._settings.get_enum(SHOW_INDICATOR_KEY) === ShowIndicator.ALWAYS; - } - } - - _manageScreenBlankState(isApp) { - let blankState = this._settings.get_enum(SCREEN_BLANK) === ControlContext.ALWAYS; - if (isApp) { - blankState = this._settings.get_enum(SCREEN_BLANK) > ControlContext.NEVER; - } - - if (blankState) { - this.inhibitFlags = 4; - } else { - this.inhibitFlags = 12; - } - } - - _manageNightLight(isEnable, isApp) { - let nightLightPref = this._settings.get_enum(NIGHT_LIGHT_KEY) === ControlContext.ALWAYS; - if (isApp) { - nightLightPref = this._settings.get_enum(NIGHT_LIGHT_KEY) > ControlContext.NEVER; - } - if (isEnable && (nightLightPref || this._nightLight && this._proxy.DisabledUntilTomorrow)) { - this._proxy.DisabledUntilTomorrow = false; - this._nightLight = false; - } else if (!isEnable && nightLightPref) { - this._proxy.DisabledUntilTomorrow = true; - this._nightLight = true; - } - } - - _sendOSDNotification(state) { - const nightLightPref = - this._settings.get_enum(NIGHT_LIGHT_KEY) !== ControlContext.NEVER; - if (state) { - let message = _('Caffeine enabled'); - if (nightLightPref && this._nightLight && this._proxy.NightLightActive) { - message = message + '. ' + _('Night Light paused'); - } - Main.osdWindowManager.show(-1, this._iconActivated, - message, null, null); - } else { - let message = _('Caffeine disabled'); - if (nightLightPref && !this._nightLight && this._proxy.NightLightActive) { - message = message + '. ' + _('Night Light resumed'); - } - Main.osdWindowManager.show(-1, this._iconDeactivated, - message, null, null); - } - } - - // Add the name of App as subtitle - _updateAppSubtitle(id) { - const listAppId = this._appInhibitedData.keys(); - let appId = id !== null ? id : listAppId.next().value; - if (appId !== undefined) { - let appInfo = Gio.DesktopAppInfo.new(appId); - this._caffeineToggle.subtitle = appInfo !== null - ? appInfo.get_display_name() - : null; - } - } - - // Add the timer duration selected as subtitle - _updateTimerSubtitle() { - if (!this._settings.get_boolean(TOGGLE_STATE_KEY)) { - const timerDuration = this._settings.get_int(TIMER_KEY); - this._caffeineToggle.subtitle = timerDuration !== 0 - ? parseInt(timerDuration) + _(' minutes') - : null; - } - } - - _updateAppConfigs() { - this._appConfigs.length = 0; - this._settings.get_strv(INHIBIT_APPS_KEY).forEach((appId) => { - // Check if app still exist - const appInfo = Gio.DesktopAppInfo.new(appId); - if (appInfo) { - this._appConfigs.push(appId); - } - }); - - // Remove inhibited app that are not in the list anymore - let inhibitedAppsToRemove = [...this._appInhibitedData.keys()] - .filter((id) => !this._appConfigs.includes(id)); - inhibitedAppsToRemove.forEach((id) => { - this._manageScreenBlankState(true); // Allow blank screen - this._manageNightLight(true, true); - this.removeInhibit(id); // Uninhibit app - }); - - this._updateAppEventMode(); - } - - _updateMainState() { - if (this._settings.get_boolean(TOGGLE_STATE_KEY) !== this._state) { - this.toggleState(); - } - // Add timer duration as Subtitle when disable - this._updateTimerSubtitle(); - } - - _saveUserState(state) { - this._userState = state; - this._settings.set_boolean(USER_ENABLED_KEY, state); - } - - _saveMainState(state) { - this._state = state; - this._settings.set_boolean(TOGGLE_STATE_KEY, state); - } - - _resetAppSignalId() { - if (this._appStateChangedSignalId > 0) { - this._appSystem.disconnect(this._appStateChangedSignalId); - this._appStateChangedSignalId = 0; - } - if (this._appDisplayChangedSignalId > 0) { - global.display.disconnect(this._appDisplayChangedSignalId); - this._appDisplayChangedSignalId = 0; - } - if (this._appWorkspaceChangedSignalId > 0) { - global.workspace_manager.disconnect(this._appWorkspaceChangedSignalId); - this._appWorkspaceChangedSignalId = 0; - } - if (this._appAddWindowSignalId > 0) { - this._activeWorkspace.disconnect(this._appAddWindowSignalId); - this._appAddWindowSignalId = 0; - } - if (this._appRemoveWindowSignalId > 0) { - this._activeWorkspace.disconnect(this._appRemoveWindowSignalId); - this._appRemoveWindowSignalId = 0; - } - } - - _updateAppEventMode() { - let appsTriggeredMode = this._settings.get_enum(TRIGGER_APPS_MODE); - - if (this._appConfigs.length === 0) { - this._resetAppSignalId(); - } else { - switch (appsTriggeredMode) { - // TRIGGER APPS MODE: ON RUNNING - case AppsTrigger.ON_RUNNING: - if (this._appStateChangedSignalId === 0) { - this._appStateChangedSignalId = - this._appSystem.connect('app-state-changed', - this._appStateChanged.bind(this)); - } - // Check if currently running App - this._appConfigs.forEach((id) => { - let app = this._appSystem.lookup_app(id); - if (app && app.get_state() !== Shell.AppState.STOPPED) { - this._appStateChanged(this._appSystem, app); - } - }); - break; - // TRIGGER APPS MODE: ON FOCUS - case AppsTrigger.ON_FOCUS: - if (this._appDisplayChangedSignalId === 0) { - this._appDisplayChangedSignalId = - global.display.connect('notify::focus-window', - this._appWindowFocusChanged.bind(this)); - } - // Check if currently focused App - this._appWindowFocusChanged(); - break; - // TRIGGER APPS MODE: ON ACTIVE WORKSPACE - case AppsTrigger.ON_ACTIVE_WORKSPACE: - if (this._appWorkspaceChangedSignalId === 0) { - this._appWorkspaceChangedSignalId = - global.workspace_manager.connect('workspace-switched', - this._appWorkspaceChanged.bind(this)); - } - // Check if App is currently on active workspace - this._appWorkspaceChanged(); - break; - } - } - } - - _toggleWorkspace() { - // Search for triggered apps on active workspace - this._appConfigs.forEach((appId) => { - let app = this._appSystem.lookup_app(appId); - let isOnWorkspace = app.is_on_workspace(this._activeWorkspace); - if (isOnWorkspace && !this._isToggleInhibited(appId)) { - this._manageScreenBlankState(true); // Allow blank screen - this._manageNightLight(false, true); - this.addInhibit(appId); // Inhibit app - } else if (!isOnWorkspace && this._isToggleInhibited(appId)) { - this._manageScreenBlankState(true); // Allow blank screen - this._manageNightLight(true, true); - this.removeInhibit(appId); // Uninhibit app - } - }); - } - - _appWorkspaceChanged() { - // Reset signal for Add/remove windows on workspace - if (this._appAddWindowSignalId > 0) { - this._activeWorkspace.disconnect(this._appAddWindowSignalId); - this._appAddWindowSignalId = 0; - } - if (this._appRemoveWindowSignalId > 0) { - this._activeWorkspace.disconnect(this._appRemoveWindowSignalId); - this._appRemoveWindowSignalId = 0; - } - - // Get active workspace - this._activeWorkspace = global.workspace_manager.get_active_workspace(); - - // Add signal listener on add/remove windows for the active workspace - this._appAddWindowSignalId = - this._activeWorkspace.connect('window-added', (wkspace, window) => { - const type = window.get_window_type(); - // Accept only normal window, ignore all other type (dialog, menu,...) - if (type === 0) { - // Add 100 ms delay to handle window detection - this._timeWorkspaceAdd = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { - this._toggleWorkspace(); - this._timeWorkspaceAdd = null; - return GLib.SOURCE_REMOVE; - }); - } - }); - this._appRemoveWindowSignalId = - this._activeWorkspace.connect('window-removed', (wkspace, window) => { - const type = window.get_window_type(); - // Accept only normal window, ignore all other type (dialog, menu,...) - if (type === 0) { - // Add 100 ms delay to handle window detection - this._timeWorkspaceRemove = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { - this._toggleWorkspace(); - this._timeWorkspaceRemove = null; - return GLib.SOURCE_REMOVE; - }); - } - }); - - // Check and toggle Caffeine - this._toggleWorkspace(); - } - - _appWindowFocusChanged() { - let winTrack = Shell.WindowTracker.get_default(); - let appId = null; - let app = winTrack.focus_app; - - if (app) { - appId = app.get_id(); - } - if (this._appConfigs.includes(appId) && !this._isToggleInhibited(appId)) { - this._manageScreenBlankState(true); // Allow blank screen - this._manageNightLight(false, true); - this.addInhibit(appId); // Inhibit app - - // Uninhibit previous focused apps - this._appInhibitedData.forEach((data, id) => { - if (id !== appId && id !== 'user') { - this.removeInhibit(id); - } - }); - } else if (!this._appConfigs.includes(appId) && this._appInhibitedData.size !== 0) { - this._manageScreenBlankState(true); // Allow blank screen - this._manageNightLight(true, true); - // Uninhibit all apps - this._appInhibitedData.forEach((data, id) => { - if (id !== 'user') { - this.removeInhibit(id); - } - }); - } - } - - _appStateChanged(appSys, app) { - let appId = app.get_id(); - let appState = app.get_state(); - - if (this._appConfigs.includes(appId)) { - // Block App state signal - appSys.block_signal_handler(this._appStateChangedSignalId); - - // Allow blank screen - this._manageScreenBlankState(true); - - if (appState === Shell.AppState.STOPPED && this._isToggleInhibited(appId)) { - this._manageNightLight(true, true); - this.removeInhibit(appId); // Uninhibit app - } else if (appState !== Shell.AppState.STOPPED && !this._isToggleInhibited(appId)) { - this._manageNightLight(false, true); - this.addInhibit(appId); // Inhibit app - } - - // Add 200 ms delay before unblock state signal - this._timeAppUnblock = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { - appSys.unblock_signal_handler(this._appStateChangedSignalId); - this._timeAppUnblock = null; - return GLib.SOURCE_REMOVE; - }); - } - } - - destroy() { - // Remove all inhibitors - this._appInhibitedData.forEach((data, appId) => this.removeInhibit(appId)); - this._appInhibitedData.clear(); - - // Remove ToggleMenu - this.quickSettingsItems.forEach((item) => item.destroy()); - - // Disconnect from signals - if (this._settings.get_boolean(FULLSCREEN_KEY)) { - this._screen.disconnect(this._inFullscreenId); - } - if (this._inhibitorAddedId) { - this._sessionManager.disconnectSignal(this._inhibitorAddedId); - this._inhibitorAddedId = 0; - } - if (this._inhibitorRemovedId) { - this._sessionManager.disconnectSignal(this._inhibitorRemovedId); - this._inhibitorRemovedId = 0; - } - if (this._windowCreatedId) { - this._display.disconnect(this._windowCreatedId); - this._windowCreatedId = 0; - } - if (this._windowDestroyedId) { - global.window_manager.disconnect(this._windowDestroyedId); - this._windowDestroyedId = 0; - } - if (this._timeOut) { - GLib.Source.remove(this._timeOut); - this._timeOut = null; - } - if (this._timePrint) { - GLib.Source.remove(this._timePrint); - this._timePrint = null; - } - if (this._timeFullscreen) { - GLib.Source.remove(this._timeFullscreen); - this._timeFullscreen = null; - } - if (this._timeWorkspaceAdd) { - GLib.Source.remove(this._timeWorkspaceAdd); - this._timeWorkspaceAdd = null; - } - if (this._timeWorkspaceRemove) { - GLib.Source.remove(this._timeWorkspaceRemove); - this._timeWorkspaceRemove = null; - } - if (this._timeAppUnblock) { - GLib.Source.remove(this._timeAppUnblock); - this._timeAppUnblock = null; - } - this._resetAppSignalId(); - - // Disconnect settings signals - if (this.inhibitId) { - this._settings.disconnect(this.inhibitId); - this.inhibitId = undefined; - } - if (this.stateId) { - this._settings.disconnect(this.stateId); - this.stateId = undefined; - } - if (this.timerId) { - this._settings.disconnect(this.timerId); - this.timerId = undefined; - } - if (this.showTimerId) { - this._settings.disconnect(this.showTimerId); - this.showTimerId = undefined; - } - if (this.indicatorId) { - this._settings.disconnect(this.indicatorId); - this.indicatorId = undefined; - } - if (this.showIndicatorId) { - this._settings.disconnect(this.showIndicatorId); - this.showIndicatorId = undefined; - } - if (this.triggerId) { - this._settings.disconnect(this.triggerId); - this.triggerId = undefined; - } - - this._appConfigs.length = 0; - this._settings = null; - super.destroy(); - } -}); - -export default class CaffeineExtension extends Extension { - enable() { - this._settings = this.getSettings(); - this._caffeineIndicator = new Caffeine(this._settings, this.path); - - // Register shortcut - Main.wm.addKeybinding(TOGGLE_SHORTCUT, this._settings, - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.ALL, () => { - this._caffeineIndicator.toggleState(); - }); - } - - disable() { - this._caffeineIndicator.destroy(); - this._caffeineIndicator = null; - - // Unregister shortcut - Main.wm.removeKeybinding(TOGGLE_SHORTCUT); - } -} diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-infinite-timer-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-infinite-timer-symbolic.svg deleted file mode 100644 index be4fdb2..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-infinite-timer-symbolic.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-long-timer-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-long-timer-symbolic.svg deleted file mode 100644 index d354294..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-long-timer-symbolic.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-medium-timer-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-medium-timer-symbolic.svg deleted file mode 100644 index 26e802b..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-medium-timer-symbolic.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-short-timer-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-short-timer-symbolic.svg deleted file mode 100644 index c3091d7..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/caffeine-short-timer-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/applications-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/applications-symbolic.svg deleted file mode 100644 index 87f307f..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/applications-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/general-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/general-symbolic.svg deleted file mode 100644 index e11da07..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/hicolor/scalable/actions/general-symbolic.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-off-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-off-symbolic.svg deleted file mode 100644 index e6d7f40..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-off-symbolic.svg +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - - - - - Gnome Symbolic Icon Theme - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-on-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-on-symbolic.svg deleted file mode 100644 index 3a730d2..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/my-caffeine-on-symbolic.svg +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - - - - - Gnome Symbolic Icon Theme - - - - - - - - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/stopwatch-symbolic.svg b/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/stopwatch-symbolic.svg deleted file mode 100644 index 57a69d6..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/icons/stopwatch-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ca/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ca/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index f9f4a6bdf31a4c2f6f711f7dfa6f3d33aaeca826..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6692 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 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/es/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/es/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index 8873f0582acc9a9c1eb5f377695481f38c658269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2177 zcmZ{k&ug4T7{^DAT34&J)mEj-2nq@G-R!Pd!^V_u(j=xfZAi9K@gS4;eRg;1`_8=1 z%$t}T^(qL8coRx53VKlQUIKzALGY>+{0F>v)$jAZ?`9LkVP`)x&pY${ntA5;(^H=d zv}e)JqyLHiGWs|7;ScTd{X(1od*B=3Rqz4uGw>ns3vdej5_}H43%&;a2=czaYyJa1 zj`;~}eiA$fo&smUhrup53oh1j2lD=pzz4yPYx$=j>$wY_1-}P*-OsiBS8y8hdmzWu zfOCH!mX|-$Bd?XEY_GjGS zUfHl+oJQxpte<`3#=edl+vl8c-p-)2{b$gj`miBw<$1Dz&xhMdbk5B=o}l3<%k~KW z%S@XhkQY6fY9FK>NFSUwLw`Y%ibpcGCMaznk;+Jw=c$fW(AG$u$mxXqd%@;%pi`1Y zWi%stNg{gbuG)jnJg@#_7^xtkcQ_;`m(*ZD+K}iK!Ddhvt2Et{WYjja?2ZU_N>dO8 za$XLKH1)9~e8_A9V)>}mqn3_^ z>ZL0TCqb-O$64?a8Q_eGH8VhZ0*ULi1JgGQLaAbigWe&rNf~9^2-^pRRh#64btL0D z3AK1@WL=1hATZdK+9aH1L|9IZ4SG?KJ-ECcrTCcQPjcdw>sPB~VDF@M&TjYk?$}3H|esIUVU(mjMJyYeN2}kj* znOq)bN~g`(W|yGA3=1`+s81@x_FNh5M~C9BB;QzHTVI|8)NZyKOSr1IF;Ranhid_G z&Ekl)nV0cMIZt8XW`8A`o2+9G2jrq<6Waub+m&8i}jc5|+I@yI?>E*@>bY}A6`=4|0A O80MvghX`eS)Zo8%Fkc-2 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/fr/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/fr/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index fc7073d54b24590abaaa2261aa512687d309d07f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6634 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 E0E63&*#H0l diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/it_IT/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/it_IT/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index 822f5c579827b4f3c61326246083fcc9aa38f010..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6513 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 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ja/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ja/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index 06ecd3b95318f044b9cf447f6fb4aa852eb384ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1670 zcmZ{k-)kII6vs!6zt$hs)(3xcMFf8^o6U+POiZvz6AdQqlCDxvkek`NySJUaGt8aM zb{~Z9OpP&72tuooVoVzCkJO5Y)s~jL_#mQSK@fZh$aOc#Kj2GW{NCAZHiUZEJD+>b zxpU9=oLzQxXUA~^_7K+NSXZ!~zT}P4cY?dYPOuNu=LL8>SOIr}?}EF)Sx~>X1nT>~Z{>dipN9V@_$z8% z2X+0Q@zA<{1Mdd^0G|R^TfQ!`1AYR041Bc3-7SuRy1oEk18bnZ?-x+NcMW_J{2P22 z)Je@pK%Gyw{C@Cx_-}!b7x$*`y%!6iP1Ez%^UJ-M8*$EnaNww~v3n+Dt!#Njf~0ci}-e4cT^Ha8^8OU!S( zIWFnA!*cBi6V1S0E_l6={5r0p~9Y^lg4@ykMRQ80!@o(mo@V;`G9 zrG30m49H0Q^k`Y4)Yg#CWVwXce&JMGHSB;-Fk_6BSZSR3L9VogLBHV!ITTRMl zC@3<*MNS7@pP+Xg2wabNR4~WL`0gQQ2j+0je3SVS!?8#~xFu%FB6A#*9SNAwVbg9+ zDlx`9*AL85S>QRdzg&=J*0o3?v)>$J6Ffe<7m6&BPNiQoQ{86QOQb7prBW}X(y3Hp zgv!9o`cz0qOR`9Y9;U8O4|DRecVqiXp>!l^yQMxH7lkq{Ff+?&$s$8O6LxVkYLP=U zF*-at*jC?_OeF?f0of>1^`Ij_6P@^~xac8vk@}Jay>DcP%b5PiB4quW* zy2p8tIA~^Emg9l>I;&P(KPN}uJAyz%BbW8)!#J==4Qv-9iG)wN>__32AD&oxed5a*)zRd`B;C=FHTaiO7W zM$0-BexqeUCG`D|?)ruK^@R@`bD^p&H?PD-)#g+k4Nj5ze4k>b`FEU z{nN4TDHWYd;uM_!d|JTR|TrKg;1{F&F_K1lNJjgPXud!9yV3i-DA%3qA&(0oQ^h@LBLSxC!*a z_p9J+8TK9ED)4=91t`JSz%lRz@CR@mcpE&6nwOwR%JWMkMfKhWp8|gdmx8~8WPb}`_!syN*p5pabU^ZZ7K96S9()P>Dm=dhQeHoTYrtPYioc|V zu`cjckn~Q2f^`5YV zqnm8MI3gUj-$*1~zBl+y?Qm?fTKfLxde{LAx>aMwT;qsfU3x|es2AsskeQU=O^(<> zkrJt1G(ft#D;irW&(tvq!8zAsjx8mZLQ3>phTeK@+m*19uI&gO3tJev>K5oOykHEP zgrer@F&DBMZZddZ&BhGMlEQVNM1*xG?V}JhPF=E{>UKff?r~Htx;ioO)_Us#S5!qt zHarH+sy8aQLb=u>QVZyy(ai3JHA2#wW<7QyVG5dO%zjWtwHVh<2%I_9Qfm{o5-J8# zcRBW95p%UYaqR;PG-U1MEeA!~c3f?rOc-%(TP7j39vjD92egCYh(VXM9q3ahZ;!UO zYtao_Ta>p&JKtWrCb}USZP|;CX+4f^Nt1Nz)cFVp!`*t>xYl}o%wqx$_0ct(R(n!J;pSZ1Q6aN=B z@>o)L(7w%wdUk2+8}}%eKH+FPt(YB0YdiV+Uc+taGBX%#4HKV|o!m+XTe-PyBd`9s zIl8gsL#;ahK_OkXh#M|n8;M5R@TR)ew&_x&bvN0`Bav48BrH26G?^5psUbIE1&Y-M zQ%gY};WW&

?XU2vd9;i854qgn4lVg9>{H#yDs?BMg|bE-JNy~`CfIikjARWZx` z)0h4Hw4X0<@0%I#LXr9TZ`Fyxg|@Xkp*dzm)u2v>{Pw_n!=6JS+x^^ zhLc0yXQK-Q^rnWHD$aT338wNx9DN1n=F8bo`mjym4)3T+R@c=VDInpS>UAD;HI_}~!vU!wfqd$ssn1>Xt2 kk0vElX+TY0YAB(K6X9D5?M+Rp8)d#=AV}oer&|~KZ-9`hBLDyZ diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/nl/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/nl/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index fff44cce9436319233134df93790ad808320e164..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5998 zcmbuCON<;x8OJLx9-HuTNO%N7Ve;4|?)7@@#K}4~S$q9T{8;Rb2^JEn>8_b+Pfz!# zt9vIKE;&Sk3z0zK#7jsK2TO#63lbb60YaQOfD{oRk>C=<0ZTbVBI3aBtA5Pv`T>E~ z^!%r)tG@mo|L?1BUf*`(w-nbQ?oV*B}F7QL(ZcyYL z2Is(YH9if_GQJ4%QNQO)8w{e`bj zgMSBQ-7W8}?A!)^l=0p5_yBk-94LN#23!Sy0E#_tg1f=%W|X=eydRYJ zo&Ytt20jdypy=@vP~`j^l>L7I#oup$v*6p{cJMPdbAv}frql)SBVY+?@ay0__yTwb z_!{^z@SorV;H|e1L-0{h#^*t?^BW)^b&)U8_ov{4;BUcKu0wZ>KF|1dl#~4r@r8-% zI4FKO3yQoRC~^KCNT}5-pv3hxP~=|%KMVe=#(Qz%qm0jhvi`fE_~Us{_WcMH{a*$} z&sRb5>zm*lcn^z2-YO{jz5?C{J_CwAFV^@5xRddnIQ4VjDNy45EGT||4wU^bfnwLs zK=JdhKw0-UQ0)9ijn^{}y>16T3@(7O?{Gan4a)uq?1EndQCVFA9|2{P*s~0Z-RHp_ zpaBno&w?WFcc8@o&mb;SH{Dj@ZJ^k9Hz@jl2^1c0fWn_|gA)IXpzQxOD15sF-U;p? z$b8ged`bRvKwPB01B#zs0EJhtgQ%?D0%hL}lPlmH2rayhfZE3`e1v8`{{e5OP4szdHkHxogNp9k*_7ctsPxf<5 ze8sm*+~OPY3-0iIlAMw29&X9g<~qO+iO-&TLbxWE#2za6Yk_Zx!QItRT@MNew{uI( zMYva`F*lC-ZPGTD&?_kF~FBzK+rBsV(yR4%)t1 zkF#7grnNuxT0FFqc^$>BGPqgUdf-q$%bZ1L{A)HO8cvVnB)LpgwPL%bObXq%aj#$K zZkGF9quh3FZqv}p#x%;t?aFZ+75!^2jNK?P8|ttRhhI5mqv+B+O0y#F)->TgSBa-a zr`FV3=w!;P+d3eIhB{9Dr0{KIQkyid+p?(;Z(enA6{+dyp!tN;PUmGRj8sRmuylOq zm796LXU)ATAX{k=xb;5hfjXeVo3I8p5mS;)DvFQgRQ#!~$J(XKm4rOlI&+2pvA1m{G3aVAvN!CWX+MuUo zs590idX%}?=Q8Q%Y@Pk4D4lK`zS$J~PqxHqn3NHznXbn!CN*`IS_BU5u!HAaVQ@=3 z6tX7bBR`J|^2|BytaB6*SF6{_vcj>);TfyLCi!bobwtjhp-5}8b!dxz7I`8H`{q@% zKyqV39Z5$M7D9LkE&?h)B;N0sT@Y?I_p`hR%cA|Ei;PdNhkcDOziK>*udE&GO?1D) zR27uEitTJE@Ary@;_j9)Lh_d2eu-#2c@7V~54NoF6{K3;(*FueuBOV!hH-a8OX}#^ zVVstQb#rYos4^8a+^>?IVU)9CdPTz;r0v@ zNnw)8skJHut_e>ymcq@6<3m^l5-s2Z+kBXth}{d-JRjHU62Cke`7^D}wdR2@(vOoc z2TfR=Tta{_u_jmNYM!_1|CjlqR`cwF4U6D-6rAHwfbmPZmu5p7xV}x2z&=^nRHlQ5 z^D}4c2qFe2T`!J;gJsVJYuS>XSv?(`v664BT_M4i^y0$e?qFdtSlFv~?O9sfec!^a zg@qX@N5NWdQip@Hd`Ta(1U1#fg%dS#`eB3=R0iiB>9Tfc;$%L|h6mW0_Da*U!J0M0 zCB0G>VZWVR(rGet^7zTa6FYXzFU%aGYH{8LYa1gpDllg!XGEOt(_!D_gWF1^uVsUeKSu4tC@}B zB6!Sh&|yUG1ja1sFHasEG|rAp(O=T@lgYDLnTPgJrP7kFbb2DFYPt7PC06gAUz}f@ z+DGui{wm^v1q9CT^q(1Z7>6eD1&SIq2(t$^rL!40rpLzQ>vRG(8E9#CiVStAb#zoT zOdY#U0i8{a8R{}F^nBew1szHsmAY!5Y*&wMKA=yEpub(uY|oN)A?)_s9L^nZkoYeOKRyAIiZErq6SF7!Pw)E=OBWjrX< zQ5)r^C;gXKtNjs(b%P`uv@_CvqVSaKnoaU#lTVLY!e)qkKjVm+^2a0+mzjT7Vh&*< z`nq0WwGc-_xt`HI+mc3Yo$|o>MaivKb|6}G&81(kHt(5rON-JvT6f|LTb(kkBQfJ( z8QMg064qXkK!FtN&ED|an5Dtt=6m0ty=}`j7Bud^ zZ2hz)qS`wRc-6}t#0S$x*RQD%%^Vd zs@^Wk;)3SPmSb2)Q_2ep=bJnJJry*T{h~v~vc9K0)y@fhGN_q%@{H=CHa~&9)CqO6 ziHH1I5}W1S5*_+G+nwH1i;_abp9R7o`>D)o#h6HHiN(qRjaX#|;er}vyiT-R(oMpJ zmBPYJmhNCk+vj+(f0)L$2sm-!4S$NDr?fGg2K|iIFjdERLqTC8s<{n0A{hCTm{qCa zjCM{6n18wN1#PW2WiS`TYv(f*!5Adsq~yu}ON>8TODE%eO{to}Dup%$IZo$E_^I4% z_$l=!rRN<|z;#bDSBg0br)`vCNxme(OLTrsa3{ZHZz~M}Qrkq>Q}mRU*B)=E0_{>% zZ{t~y|Hq`;B35X;CABc34c=wRv{o0nMu}!PEv9)URlz4)vxwMH#p*)PmX}Qq=HGo! z+}LJwJ4n>~p(nT+=_`zcAj ziV+k~{`S@#<+4!bagL!$MC&{hZuIWs2{CyqU`Jsl>? zN<0E@0V`gC?sx_S3wCVTb36$R*8KW>j(v{*vHX2;;UmFu8}$g4pzfePq5SxPx`z6R zx`FzIx`q0Ux{LaQx`$f0LP#C?0C^qRM*93N@*C>yEWd=!e4je3z@^HQkNvnhMRg8YPZF{&3tn2X$@_f}3N9zKE5=~v zAt>IHkdSsoS`0u@PW!o(Ha6gcER!PUPH07ir6yNOsFWPQ8MZl8vYge#PMiVh7(Im8 zv7Lk+gRxi?(NyU%FgpM#8N7F(e452GXTcF<+BmjvQ<1QZJhiN=BN}uL*%6$HYVQ_z z5YcAXSZ0log-zOc7B!zf2^(P;>~ZT@*KlPeciKd>BeXO0L^v1wpLw47_(d^`YdtZk zWpWMcRGRY?SQq#htF#n$aG8y0CWHN*{r3Df8nrOk)C&FMd1Z!%9R5u`lU%44jR)LV zaI3Go+iYdN&-?0wVQm%b1n(`PD?Q)E@zlg!NB z%$>302&v5r{{e_1Bm_n6L+MK;Bpv_>EQENgR3QXX`@joQB_7}bsURUf=g#a8*HOi2 z?|$e0K0m(aoO$cPyT7Y=9;bbZ_RBkzS_Z#)7k@lA?pErn;4b(8_*+n>-T)s2{{-Fx zzTM3K1LUXfe4kQBz(Wl_48EWK=?2e%_tU=!ei*zA%J~Cu2E5haE8sN!KZ1wA|AMpN zJzUDGIswYQQ=rVRfO5|z@N?j0P}V&UioD+e9|B)!`mcc>q5nHj&iOMaa=i^62HyeY z+z0s6;6vak@XMgwvki*fo&#my4?(%-6;R~7|5u>+;osmKc$CfJ_h-Q~;I}|j zRzCto&zC{*!*4)2|M%cg@bzZ=KcL8W2S)rXco>v>Pk=K1HIOCh3dm1o{E6Ma4T@b~ z09)Ws!HeJSwM*R$U6cnDF2gQ!hg0o-&iXDCe$~}Jo<(#*`Y4ARjegZrJ%6tln zzPCV;|22@M>P=Ae{5$w1@DP^~N~1^ae2n&mW<=I}k|sLMHe&+99ZWiU9&g@67qN#t zVrP+29!(RygzFNQbF_#iIz3GLJZ*+1x_pc#zL!UQAoe>(o2Ox}z#s9s@Ktn^N4WGT z?bFiX5gUk}qO&~5X{a1xUHam4@w3=`_=tbRr_go$Ea)`xrFLEI%Oc5p{xNM$+}E+o zOOxb`Xp?I*7^F#T%EaY5>FDW>_18)_(A^}pIyae}Q44XIY+JqKifevgVyhN99kr0A zZb$pLur}9QsmZS~v}1O?T9`OdB#?nH>UG&SrAC-u&ldWu>2__Ba~$&rMs?;oRxR4T z*-l)cMvI3pdNaxFcwBc9Z?;m~8LiYdZwC6#dCT3XV0J}euXmC(J#eLZ%63hamb!0~ zUcb~`SA<=I!gg(8^VrJ9yyJF8D|eDk*?-T4i65k9S1ko$^iCgZ8QrbYv@spxjP37r zQRU(pbY+k8VyN#Vz z?T$8aY*V%~_1EWLQmaA93*lclQMj}=`sBpGR34*F4i(l{8Dkgobhl9`5Jaup%w}77 z)|Up+)~)9ztK-Jc!{J854GR_U$&e12E&Hw$Y$+~kso?@~+Q{okUZO! zt2Qp9^PT8vTX<4eTlaF8*~s^8nnw0UX>%ElhTNN4w*v?ft@vKji59D#k2YOfPpw^y z*6lWOu=XiP+t%}Q^K;SMd^G&3#{Owxq3yM{DXud-O?R4w|Tys}k966Lo$ zpskr-T%TGwzp^w|`dDjj>TD1J>2?Q*U!wag87Ik~)N$Vw*z@$I&2!Po@jB6hd=@R` zvFi{lZGCbpDW{%^)|~AmW%PBsORDeq3y9LzSH=^I#@m4@`)%EtT1zYPP(*^td|T&( z(DkS1pVam1>FHdb(Z^=SyEj}_#P)10Q(M(?XdrR$Q+V23Xf> z>femoyH(h5DsJC0Y2WDuLd#J6k{G(c-!)rg#2rO~u;Uz0$Z#==RNJ8%Ggardb z$LOn)3WHs6PB-bXWbfs@pIc8YE2Q`TZ`kA@6}(bV?XOn`&BfDWgKG+7@J>ukH=2q> zc4YAlOKmU^LoH5Hz_YN-`*F?1Ayk~G(NH$B^`M3DzINQ$G-|y3UA!3i z9wSJd?umlUstcRgcQ`UE*$t2C;ZY&4 zMH74)eKB@uMMf|8~P zLkp#fNq*_8d|3oZYo_cY#zAg6z1(mC%1-2?5sjN^wZGB_Po_x*^2O{^7uVTIQ*rlR R-Nv{OK|Wr_nnDz-{s*pK@Y(bkw6Fui3JNULCDjji>gW=qK_%6+G$6fq3Qyua+5nVhQtoGGi6xu z6MR7zY~U+KtoR2W3wCVTbDWe8R*sIZ@6*otc7N_efOQ*q1Z2P+;1l5258xW`6Sx8V z0&W4nfxEyT;2tn{B?#uh55U*KZLmMz1%C%#0=~xziupR*U|**Leh5AS`*;oB0>20Q zI$ywkp08k(sL$rWzLsA%0l4Z~-uCNiLv^2EJ!b2*xalB)PGUFT7(DJ@cSlB(_hcuRT?3Qqp zu!SgI!S|8dhRRyicM?SQk@N!-_0jdJ~z|*`^2p%+|&veLE}k@$sDdVU*8Dv0gZWyO+QZ0H6!bVWFW#+8-tC~tk4Lg)J)Hr#JfwQgZ)aS NBIrR`IH*hO;4cwX7LWh{ diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ru/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/ru/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index 99b5ca5e6cb49017796936bf880aa04c8e616402..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8503 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 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/sv/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/sv/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index bfb31f6a8c7d79a9bca83b28ef9d8a386d5054df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1343 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 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-caffeine.mo b/.local/share/gnome-shell/extensions/caffeine@patapon.info/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-caffeine.mo deleted file mode 100644 index c6bef06660e11c0b6647cc2218630d08beb57e18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5870 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 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/metadata.json b/.local/share/gnome-shell/extensions/caffeine@patapon.info/metadata.json deleted file mode 100644 index b399c32..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/metadata.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Disable the screensaver and auto suspend", - "donations": { - "paypal": [ - "eonpatapon", - "stuartahayhurst", - "pakaoraki" - ] - }, - "gettext-domain": "gnome-shell-extension-caffeine", - "name": "Caffeine", - "settings-schema": "org.gnome.shell.extensions.caffeine", - "shell-version": [ - "45" - ], - "url": "https://github.com/eonpatapon/gnome-shell-extension-caffeine", - "uuid": "caffeine@patapon.info", - "version": 52 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/appsPage.js b/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/appsPage.js deleted file mode 100644 index b57b414..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/appsPage.js +++ /dev/null @@ -1,220 +0,0 @@ -/* - This file is part of Caffeine (gnome-shell-extension-caffeine). - - Caffeine 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. - - Caffeine 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 Caffeine. - If not, see . - - Copyright 2022 Pakaoraki - - // From https://gitlab.com/skrewball/openweather/-/blob/master/src/prefs.js -*/ -/* exported AppsPage */ -'use strict'; - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export var AppsPage = GObject.registerClass( -class CaffeineAppsPage extends Adw.PreferencesPage { - _init(settings, settingsKey) { - super._init({ - title: _('Apps'), - icon_name: 'applications-symbolic', - name: 'AppsPage' - }); - this._settingsKey = settingsKey; - this._settings = settings; - this._listApps = []; - - // Apps behavior group - // -------------- - let appsBehaviorGroup = new Adw.PreferencesGroup({ - title: _('Trigger mode') - }); - - // Apps behavior select mode - let appsTriggerMode = new Gtk.StringList(); - appsTriggerMode.append(_('Running')); - appsTriggerMode.append(_('Focus')); - appsTriggerMode.append(_('Active workspace')); - let appsTriggerModeRow = new Adw.ComboRow({ - title: _('Apps trigger Caffeine mode'), - subtitle: _('Choose the way apps will trigger Caffeine'), - model: appsTriggerMode, - selected: this._settings.get_enum(this._settingsKey.TRIGGER_APPS_MODE) - }); - - // Add elements - appsBehaviorGroup.add(appsTriggerModeRow); - this.add(appsBehaviorGroup); - - // Apps list group - // -------------- - let addAppsButton = new Gtk.Button({ - child: new Adw.ButtonContent({ - icon_name: 'list-add-symbolic', - label: _('Add') - }) - }); - this.appsGroup = new Adw.PreferencesGroup({ - title: _('Apps that trigger Caffeine'), - header_suffix: addAppsButton - }); - - this._refreshApps(); - - // Add elements - this.add(this.appsGroup); - - // Bind signals - addAppsButton.connect('clicked', this._onAddApp.bind(this)); - appsTriggerModeRow.connect('notify::selected', (widget) => { - this._settings.set_enum(this._settingsKey.TRIGGER_APPS_MODE, widget.selected); - }); - } - - _refreshApps() { - const _apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); - - // Clear the Apps list - this._listApps.length = 0; - - // Update the list & Check if app still exist - _apps.forEach((id) => { - const appInfo = Gio.DesktopAppInfo.new(id); - - if (appInfo) { - this._listApps.push(id); - } - }); - - // Check if the apps list UI needs updating - if (this._appsListUi !== this._listApps) { - // Remove the old list - if (this._count) { - for (let i = 0; i < this._count; i++) { - this.appsGroup.remove(this.apps[i].Row); - } - this._count = null; - } - - if (this._listApps.length > 0) { - this.apps = {}; - - // Build new apps UI list - for (let i in this._listApps) { - this.apps[i] = {}; - this.apps[i].ButtonBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - halign: Gtk.Align.CENTER, - spacing: 5, - hexpand: false, - vexpand: false - }); - this.apps[i].DeleteButton = new Gtk.Button({ - icon_name: 'edit-delete-symbolic', - valign: Gtk.Align.CENTER, - css_classes: ['error'], - hexpand: false, - vexpand: false - }); - - // App info - let appInfo = Gio.DesktopAppInfo.new(this._listApps[i]); - const appIcon = new Gtk.Image({ - gicon: appInfo.get_icon(), - pixel_size: 32 - }); - appIcon.get_style_context().add_class('icon-dropshadow'); - this.apps[i].Row = new Adw.ActionRow({ - title: appInfo.get_display_name(), - subtitle: this._listApps[i].replace('.desktop', ''), - activatable: true - }); - - // Add elements - this.apps[i].Row.add_prefix(appIcon); - this.apps[i].ButtonBox.append(this.apps[i].DeleteButton); - this.apps[i].Row.add_suffix(this.apps[i].ButtonBox); - this.appsGroup.add(this.apps[i].Row); - } - // Bind signals - for (let i in this.apps) { - this.apps[i].DeleteButton.connect('clicked', () => { - this._onRemoveApp(this._listApps[i]); - }); - } - this._count = this._listApps.length; - } - this._appsListUi = [...this._listApps]; - } - return 0; - } - - _onAddApp() { - const dialog = new NewAppDialog(this.get_root(), this._settings, this._settingsKey); - dialog.connect('response', (dlg, id) => { - const appInfo = id === Gtk.ResponseType.OK - ? dialog.get_widget().get_app_info() : null; - const apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); - if (appInfo && !apps.some((a) => a === appInfo.get_id())) { - this._settings.set_strv(this._settingsKey.INHIBIT_APPS, [ - ...apps, appInfo.get_id() - ]); - this._refreshApps(); - } - dialog.destroy(); - }); - dialog.show(); - } - - _onRemoveApp(appId) { - this._settings.set_strv(this._settingsKey.INHIBIT_APPS, - this._settings.get_strv(this._settingsKey.INHIBIT_APPS).filter((id) => { - return id !== appId; - }) - ); - this._refreshApps(); - } -}); - -const NewAppDialog = GObject.registerClass( - class NewAppDialog extends Gtk.AppChooserDialog { - _init(parent, settings, settingsKey) { - super._init({ - transient_for: parent, - modal: true - }); - - this._settings = settings; - this._settingsKey = settingsKey; - - this.get_widget().set({ - show_all: true, - show_other: true // hide more button - }); - - this.get_widget().connect('application-selected', - this._updateSensitivity.bind(this)); - this._updateSensitivity(); - } - - _updateSensitivity() { - const apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); - const appInfo = this.get_widget().get_app_info(); - this.set_response_sensitive(Gtk.ResponseType.OK, - appInfo && !apps.some((i) => i.startsWith(appInfo.get_id()))); - } - }); diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/displayPage.js b/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/displayPage.js deleted file mode 100644 index ef75d2a..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/displayPage.js +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of Caffeine (gnome-shell-extension-caffeine). - - Caffeine 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. - - Caffeine 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 Caffeine. - If not, see . - - Copyright 2022 Pakaoraki - - // From https://gitlab.com/skrewball/openweather/-/blob/master/src/prefs.js -*/ -/* exported DisplayPage */ -'use strict'; - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export var DisplayPage = GObject.registerClass( -class CaffeineDisplayPage extends Adw.PreferencesPage { - _init(settings, settingsKey) { - super._init({ - title: _('Display'), - icon_name: 'video-display-symbolic', - name: 'DisplayPage' - }); - this._settings = settings; - this._settingsKey = settingsKey; - - // Display group - // -------------- - let displayGroup = new Adw.PreferencesGroup({ - title: _('Display') - }); - - // Show indicator - let showStatusIndicator = new Gtk.StringList(); - showStatusIndicator.append(_('Only when active')); - showStatusIndicator.append(_('Always')); - showStatusIndicator.append(_('Never')); - let showStatusIndicatorRow = new Adw.ComboRow({ - title: _('Show status indicator in top panel'), - subtitle: _('Enable or disable the Caffeine icon in the top panel'), - model: showStatusIndicator, - selected: this._settings.get_enum(this._settingsKey.SHOW_INDICATOR) - }); - - // Show timer - let showTimerSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean(this._settingsKey.SHOW_TIMER) - }); - let showTimerRow = new Adw.ActionRow({ - title: _('Show timer in top panel'), - subtitle: _('Enable or disable the timer in the top panel'), - activatable_widget: showTimerSwitch - }); - showTimerRow.add_suffix(showTimerSwitch); - - // Notifications - let notificationSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean(this._settingsKey.SHOW_NOTIFICATIONS) - }); - let notificationRow = new Adw.ActionRow({ - title: _('Notifications'), - subtitle: _('Enable notifications when Caffeine is enabled or disabled'), - activatable_widget: notificationSwitch - }); - notificationRow.add_suffix(notificationSwitch); - - // Indicator position offset - this.lastIndicatorPos = this._settings.get_int(this._settingsKey.INDICATOR_POS_MAX); - this.posIndicatorOffsetButton = new Gtk.SpinButton({ - adjustment: new Gtk.Adjustment({ - lower: -1, - upper: this.lastIndicatorPos, - step_increment: 1, - page_increment: 1, - page_size: 0, - value: this._settings.get_int(this._settingsKey.INDICATOR_POSITION) - }), - climb_rate: 1, - digits: 0, - numeric: true, - valign: Gtk.Align.CENTER - }); - let posIndicatorOffsetRow = new Adw.ActionRow({ - title: _('Status indicator position'), - subtitle: _('The position relative of indicator icon to other items'), - activatable_widget: this.posIndicatorOffsetButton - }); - posIndicatorOffsetRow.add_suffix(this.posIndicatorOffsetButton); - - // Add elements - displayGroup.add(showStatusIndicatorRow); - displayGroup.add(showTimerRow); - displayGroup.add(notificationRow); - displayGroup.add(posIndicatorOffsetRow); - this.add(displayGroup); - - // Bind signals - // -------------- - showStatusIndicatorRow.connect('notify::selected', (widget) => { - if (widget.selected === 2) { - showTimerSwitch.set_sensitive(false); - } else { - showTimerSwitch.set_sensitive(true); - } - this._settings.set_enum(this._settingsKey.SHOW_INDICATOR, widget.selected); - }); - showTimerSwitch.connect('notify::active', (widget) => { - this._settings.set_boolean(this._settingsKey.SHOW_TIMER, widget.get_active()); - }); - notificationSwitch.connect('notify::active', (widget) => { - this._settings.set_boolean(this._settingsKey.SHOW_NOTIFICATIONS, widget.get_active()); - }); - this._settings.bind(this._settingsKey.INDICATOR_POSITION, - this.posIndicatorOffsetButton, 'value', - Gio.SettingsBindFlags.DEFAULT); - this._settings.connect(`changed::${this._settingsKey.INDICATOR_POS_MAX}`, this._updatePosMax.bind(this)); - } - - _updatePosMax() { - this.lastIndicatorPos = this._settings.get_int(this._settingsKey.INDICATOR_POS_MAX); - this.posIndicatorOffsetButton.adjustment.set_upper(this.lastIndicatorPos); - } -}); diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/generalPage.js b/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/generalPage.js deleted file mode 100644 index 16539df..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/preferences/generalPage.js +++ /dev/null @@ -1,387 +0,0 @@ -/* - This file is part of Caffeine (gnome-shell-extension-caffeine). - - Caffeine 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. - - Caffeine 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 Caffeine. - If not, see . - - Copyright 2022 Pakaoraki - - // From https://gitlab.com/skrewball/openweather/-/blob/master/src/prefs.js -*/ -/* exported GeneralPage */ -'use strict'; - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; -import GObject from 'gi://GObject'; -import Gdk from 'gi://Gdk'; - -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const genParam = (type, name, ...dflt) => GObject.ParamSpec[type](name, name, name, GObject.ParamFlags.READWRITE, ...dflt); - -const TIMERS_DURATION = [ - '05, 10, 30', - '10, 20, 45', - '15, 30, 60', - '20, 40, 75', - '30, 50, 80' -]; - -export var GeneralPage = GObject.registerClass( -class CaffeineGeneralPage extends Adw.PreferencesPage { - _init(settings, settingsKey) { - super._init({ - title: _('General'), - icon_name: 'general-symbolic', - name: 'GeneralPage' - }); - this._settings = settings; - this._settingsKey = settingsKey; - - // Behavior group - // -------------- - let behaviorGroup = new Adw.PreferencesGroup({ - title: _('Behavior') - }); - - // Enable / Disable fullscreen apps - let disableFullscreenSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean(this._settingsKey.FULLSCREEN) - }); - let disableFullscreenRow = new Adw.ActionRow({ - title: _('Enable for fullscreen apps'), - subtitle: _('Automatically enable when an app enters fullscreen mode'), - activatable_widget: disableFullscreenSwitch - }); - disableFullscreenRow.add_suffix(disableFullscreenSwitch); - - // Remember state - let rememberStateSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean(this._settingsKey.RESTORE) - }); - let rememberStateRow = new Adw.ActionRow({ - title: _('Remember state'), - subtitle: _('Remember the last state across sessions and reboots'), - activatable_widget: rememberStateSwitch - }); - rememberStateRow.add_suffix(rememberStateSwitch); - - // Pause and resume Night Light - let pauseNightLight = new Gtk.StringList(); - pauseNightLight.append(_('Never')); - pauseNightLight.append(_('Always')); - pauseNightLight.append(_('For apps on list')); - let pauseNightLightRow = new Adw.ComboRow({ - title: _('Pause and resume Night Light'), - subtitle: _('Toggles the night light together with Caffeine\'s state'), - model: pauseNightLight, - selected: this._settings.get_enum(this._settingsKey.NIGHT_LIGHT) - }); - - // Allow blank screen - let allowBlankScreen = new Gtk.StringList(); - allowBlankScreen.append(_('Never')); - allowBlankScreen.append(_('Always')); - allowBlankScreen.append(_('For apps on list')); - let allowBlankScreenRow = new Adw.ComboRow({ - title: _('Allow screen blank'), - subtitle: _('Allow turning off screen when Caffeine is enabled'), - model: allowBlankScreen, - selected: this._settings.get_enum(this._settingsKey.SCREEN_BLANK) - }); - - // Add elements - behaviorGroup.add(disableFullscreenRow); - behaviorGroup.add(rememberStateRow); - behaviorGroup.add(pauseNightLightRow); - behaviorGroup.add(allowBlankScreenRow); - this.add(behaviorGroup); - - // Timer group - // -------------- - let timerGroup = new Adw.PreferencesGroup({ - title: _('Timer') - }); - - const durationIndex = this._settings.get_int(this._settingsKey.DURATION_TIMER_INDEX); - this.timerOptionRow = new Adw.ActionRow({ - title: _('Durations'), - activatable: true - }); - - let adjustSliderTimer = new Gtk.Adjustment({ - lower: 0, - upper: 4, - step_increment: 0.1, - page_increment: 1, - value: durationIndex - }); - this._updateTimerDuration(durationIndex); - - let sliderTimer = new Gtk.Scale({ - valign: 'center', - hexpand: true, - width_request: '200px', - round_digits: false, - draw_value: false, - orientation: 'horizontal', - digits: 0, - adjustment: adjustSliderTimer - }); - sliderTimer.add_mark(0, Gtk.PositionType.BOTTOM, null); - sliderTimer.add_mark(1, Gtk.PositionType.BOTTOM, null); - sliderTimer.add_mark(2, Gtk.PositionType.BOTTOM, null); - sliderTimer.add_mark(3, Gtk.PositionType.BOTTOM, null); - sliderTimer.add_mark(4, Gtk.PositionType.BOTTOM, null); - this.timerOptionRow.add_suffix(sliderTimer); - - // Add elements - timerGroup.add(this.timerOptionRow); - this.add(timerGroup); - - // Shortcut group - // -------------- - let deleteShortcutButton = new Gtk.Button({ - icon_name: 'edit-delete-symbolic', - valign: Gtk.Align.CENTER, - css_classes: ['error'], - hexpand: false, - vexpand: false - }); - let shortcutGroup = new Adw.PreferencesGroup({ - title: _('Shortcut'), - header_suffix: deleteShortcutButton - }); - - // Keyboard shortcut - this.shortcutKeyBoard = new ShortcutSettingWidget( - this._settings, - this._settingsKey.TOGGLE_SHORTCUT, - _('Toggle shortcut'), - _('Use Backspace to clear') - ); - - // Hide/Show delete button - if (!this.shortcutKeyBoard.isAcceleratorSet()) { - deleteShortcutButton.visible = false; - } - - // Add elements - shortcutGroup.add(this.shortcutKeyBoard); - this.add(shortcutGroup); - - - // Bind signals - // -------------- - disableFullscreenSwitch.connect('notify::active', (widget) => { - this._settings.set_boolean(this._settingsKey.FULLSCREEN, widget.get_active()); - }); - rememberStateSwitch.connect('notify::active', (widget) => { - this._settings.set_boolean(this._settingsKey.RESTORE, widget.get_active()); - }); - pauseNightLightRow.connect('notify::selected', (widget) => { - this._settings.set_enum(this._settingsKey.NIGHT_LIGHT, widget.selected); - }); - allowBlankScreenRow.connect('notify::selected', (widget) => { - this._settings.set_enum(this._settingsKey.SCREEN_BLANK, widget.selected); - }); - sliderTimer.connect('change-value', - (widget) => this._updateTimerDuration(widget.get_value())); - deleteShortcutButton.connect('clicked', this._resetShortcut.bind(this)); - this._settings.connect(`changed::${this._settingsKey.TOGGLE_SHORTCUT}`, () => { - if (this.shortcutKeyBoard.isAcceleratorSet()) { - deleteShortcutButton.visible = true; - } else { - deleteShortcutButton.visible = false; - } - }); - } - - _updateTimerDuration(value) { - const durationIndex = this._settings.get_int(this._settingsKey.DURATION_TIMER_INDEX); - this.timerOptionRow.set_subtitle(_('Set to ') + TIMERS_DURATION[value] + _(' minutes')); - if (durationIndex !== value) { - this._settings.set_int(this._settingsKey.DURATION_TIMER_INDEX, value); - } - } - - _resetShortcut() { - this.shortcutKeyBoard.resetAccelerator(); - } -}); - -/* -* Shortcut Widget -*/ -const ShortcutSettingWidget = class extends Adw.ActionRow { - static { - GObject.registerClass({ - Properties: { - shortcut: genParam('string', 'shortcut', '') - }, - Signals: { - changed: { param_types: [GObject.TYPE_STRING] } - } - }, this); - } - - constructor(settings, key, label, sublabel) { - super({ - title: label, - subtitle: sublabel, - activatable: true - }); - - this.shortcutBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - halign: Gtk.Align.CENTER, - spacing: 5, - hexpand: false, - vexpand: false - }); - - this._key = key; - this._settings = settings; - this._description = sublabel; - - this.add_suffix(this.shortcutBox); - this.shortLabel = new Gtk.ShortcutLabel({ - disabled_text: _('New accelerator…'), - valign: Gtk.Align.CENTER, - hexpand: false, - vexpand: false - }); - - this.shortcutBox.append(this.shortLabel); - - // Bind signals - this.connect('activated', this._onActivated.bind(this)); - this.bind_property('shortcut', this.shortLabel, 'accelerator', GObject.BindingFlags.DEFAULT); - [this.shortcut] = this._settings.get_strv(this._key); - - this.add_suffix(this.shortcutBox); - } - - isAcceleratorSet() { - if (this.shortLabel.get_accelerator()) { - return true; - } else { - return false; - } - } - - resetAccelerator() { - this.saveShortcut(); // Clear shortcut - } - - _onActivated(widget) { - let ctl = new Gtk.EventControllerKey(); - - let content = new Adw.StatusPage({ - title: _('New accelerator…'), - description: this._description, - icon_name: 'preferences-desktop-keyboard-shortcuts-symbolic' - }); - - this._editor = new Adw.Window({ - modal: true, - hide_on_close: true, - transient_for: widget.get_root(), - width_request: 480, - height_request: 320, - content - }); - - this._editor.add_controller(ctl); - ctl.connect('key-pressed', this._onKeyPressed.bind(this)); - this._editor.present(); - } - - _onKeyPressed(_widget, keyval, keycode, state) { - let mask = state & Gtk.accelerator_get_default_mod_mask(); - mask &= ~Gdk.ModifierType.LOCK_MASK; - - if (!mask && keyval === Gdk.KEY_Escape) { - this._editor.close(); - return Gdk.EVENT_STOP; - } - - if (keyval === Gdk.KEY_BackSpace) { - this.saveShortcut(); // Clear shortcut - return Gdk.EVENT_STOP; - } - - if (!this.isValidBinding(mask, keycode, keyval) || !this.isValidAccel(mask, keyval)) { - return Gdk.EVENT_STOP; - } - - this.saveShortcut(keyval, keycode, mask); - return Gdk.EVENT_STOP; - } - - saveShortcut(keyval, keycode, mask) { - if (!keyval && !keycode) { - this.shortcut = ''; - } else { - this.shortcut = Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask); - } - - this.emit('changed', this.shortcut); - this._settings.set_strv(this._key, [this.shortcut]); - this._editor.destroy(); - } - - // Functions from https://gitlab.gnome.org/GNOME/gnome-control-center/-/blob/main/panels/keyboard/keyboard-shortcuts.c - - keyvalIsForbidden(keyval) { - return [ - // Navigation keys - Gdk.KEY_Home, - Gdk.KEY_Left, - Gdk.KEY_Up, - Gdk.KEY_Right, - Gdk.KEY_Down, - Gdk.KEY_Page_Up, - Gdk.KEY_Page_Down, - Gdk.KEY_End, - Gdk.KEY_Tab, - - // Return - Gdk.KEY_KP_Enter, - Gdk.KEY_Return, - - Gdk.KEY_Mode_switch - ].includes(keyval); - } - - isValidBinding(mask, keycode, keyval) { - return !(mask === 0 || mask === Gdk.ModifierType.SHIFT_MASK && keycode !== 0 && - ((keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || - (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || - (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || - (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) || - (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || - (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || - (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) || - (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) || - (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || - (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || - (keyval === Gdk.KEY_space && mask === 0) || this.keyvalIsForbidden(keyval)) - ); - } - - isValidAccel(mask, keyval) { - return Gtk.accelerator_valid(keyval, mask) || (keyval === Gdk.KEY_Tab && mask !== 0); - } -}; diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/prefs.js b/.local/share/gnome-shell/extensions/caffeine@patapon.info/prefs.js deleted file mode 100644 index 4e2fcc0..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/prefs.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of Caffeine (gnome-shell-extension-caffeine). - - Caffeine 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. - - Caffeine 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 Caffeine. - If not, see . - - Copyright 2022 Pakaoraki - - // From https://gitlab.com/skrewball/openweather/-/blob/master/src/prefs.js -*/ -/* exported CaffeinePrefs */ -'use strict'; - -import Gtk from 'gi://Gtk'; -import Gdk from 'gi://Gdk'; - -// Import preferences pages -import * as GeneralPrefs from './preferences/generalPage.js'; -import * as DisplayPrefs from './preferences/displayPage.js'; -import * as AppsPrefs from './preferences/appsPage.js'; - -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const SettingsKey = { - INHIBIT_APPS: 'inhibit-apps', - SHOW_INDICATOR: 'show-indicator', - SHOW_NOTIFICATIONS: 'show-notifications', - SHOW_TIMER: 'show-timer', - DURATION_TIMER_INDEX: 'duration-timer', - FULLSCREEN: 'enable-fullscreen', - RESTORE: 'restore-state', - NIGHT_LIGHT: 'nightlight-control', - TOGGLE_SHORTCUT: 'toggle-shortcut', - DEFAULT_WIDTH: 'prefs-default-width', - DEFAULT_HEIGHT: 'prefs-default-height', - SCREEN_BLANK: 'screen-blank', - TRIGGER_APPS_MODE: 'trigger-apps-mode', - INDICATOR_POSITION: 'indicator-position', - INDICATOR_INDEX: 'indicator-position-index', - INDICATOR_POS_MAX: 'indicator-position-max' -}; - -export default class CaffeinePrefs extends ExtensionPreferences { - fillPreferencesWindow(window) { - let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - if (!iconTheme.get_search_path().includes(this.path + '/icons')) { - iconTheme.add_search_path(this.path + '/icons'); - } - - const settings = this.getSettings(); - const generalPage = new GeneralPrefs.GeneralPage(settings, SettingsKey); - const displayPage = new DisplayPrefs.DisplayPage(settings, SettingsKey); - const appsPage = new AppsPrefs.AppsPage(settings, SettingsKey); - - let prefsWidth = settings.get_int(SettingsKey.DEFAULT_WIDTH); - let prefsHeight = settings.get_int(SettingsKey.DEFAULT_HEIGHT); - - window.set_default_size(prefsWidth, prefsHeight); - window.set_search_enabled(true); - - window.add(generalPage); - window.add(displayPage); - window.add(appsPage); - - window.connect('close-request', () => { - let currentWidth = window.default_width; - let currentHeight = window.default_height; - // Remember user window size adjustments. - if (currentWidth !== prefsWidth || currentHeight !== prefsHeight) { - settings.set_int(SettingsKey.DEFAULT_WIDTH, currentWidth); - settings.set_int(SettingsKey.DEFAULT_HEIGHT, currentHeight); - } - window.destroy(); - }); - } -} diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/gschemas.compiled deleted file mode 100644 index 4875085ffbc57693ddca7b250b457e5d688aba30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1612 zcmbtUPiPcZ9DdOx{>dLxlSt?(kP5rv>|SzETWbzNLTf!q2tvWPvu|b|nY_21d6P|` zwNj`A+JhGly?K%1$x9CwDu{THMQZCNwqa;&6h!-v{8JZg2(g0wciH!C-wt_zz}d47y(90jDwE=6Ts0D zli-`bEMDSz%yCq#i{HV20^NM6neTJ(JT|y7Hg}it)JG7%1pW;8;OFmN(WgEN{|Yz) zhJHN#FMVqI*T4^f2VY$sVLhma;BSLp56j*G>A=Q}9>7SAemvzxa?oHS5^|XTY0J?|n|6n&;XA-vB;3F+NP6n(?>5 zw}BVa;Q)PV*6kknKJe`N$N9e0jDO5|^wB@t?_Xv-^%(qF@NwYR`Cyqo^)dJhVD_G~ zVHhhfbCkFt$g1nEW!0aEC3~O^=)`EEnfu&IQqSx|Pfj$VZ&$@d= zHgSGdUY&|etJ*ZRFP%-imQA%ow<8*(qN_%Sk&F4``PR6^#>JFT>nedPlNFu9=_g43s>)6xVjK&8rinj z%ML*GSXCGkwU82KK6}fwBwu!@9 z<0Y9f+Jt>)?>D>q!V9dQ@yvM*@V`jcYujWsZAqV{>x}gB@NH&X)3%N0^jcn97BC-p z551%JUJCWEMNGt(z`7!(_1D|ED6wH_Wvzmh;*~x}jb9 z+V~9mq?sj>-O-mJ!?|9TqE1CAo3vmys(DhzIvudR_z}gol73!iuMtbLS_F%C@25ni W=-}NegnjlX+L|m%#@=Awr2ha73}2f7 diff --git a/.local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/org.gnome.shell.extensions.caffeine.gschema.xml b/.local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/org.gnome.shell.extensions.caffeine.gschema.xml deleted file mode 100644 index 6baaccb..0000000 --- a/.local/share/gnome-shell/extensions/caffeine@patapon.info/schemas/org.gnome.shell.extensions.caffeine.gschema.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - [ ] - Application list - A list of strings, each containing an application id (desktop file name) - - - false - Store caffeine toggle state - - - - false - Store caffeine user state - - - - 0 - Specify time (minutes) for the timer countdown - Specify time (minutes) for the timer countdown - - - 2 - Specify index of duration range for the timer - Specify index of duration range for the timer - - - false - Restore caffeine state - - - - "only-active" - Show indicator - Show the indicator on the top panel - - - true - Show notifications - Show notifications when enabled/disabled - - - true - Show timer - Show timer when enabled/disabled - - - true - Enable when a fullscreen application is running - Enable when a fullscreen application is running - - - "never" - Night Light control mode - Set the way Caffeine interacts with the Night light setting. - - - "never" - Allow screen blank - Allow turning off screen when Caffeine is enabled. - - - "on-running" - Trigger App control mode - Set the trigger method for apps. - - - - Toggle shortcut - Shortcut to toggle Caffeine. - - - 570 - Default width for the preferences window - - - 590 - Default height for the preferences window - - - 0 - Visible position offset of status icon in indicator menu - - - 0 - Real position offset of status icon in indicator menu that include invisible one - - - 1 - Last item index in indicator menu - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/LICENSE.rst b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/LICENSE.rst deleted file mode 100644 index 45cad82..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/LICENSE.rst +++ /dev/null @@ -1,24 +0,0 @@ -====================== -The MIT License (MIT) -====================== - -Copyright (c) 2014, Yotam Bar-On ------------------------------------------ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -*The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software.* - -**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.** diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/README.rst b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/README.rst deleted file mode 100644 index 30373ac..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/README.rst +++ /dev/null @@ -1,84 +0,0 @@ -============================ -📋 Clipboard Indicator -============================ - -.. image:: https://raw.githubusercontent.com/andyholmes/gnome-shell-extensions-badge/eb9af9a1c6f04eb060cb01de6aeb5c84232cd8c0/get-it-on-ego.svg?sanitize=true - :target: https://extensions.gnome.org/extension/779/clipboard-indicator/ - :width: 180 - :alt: Get it on GNOME Extensions - -The most popular, reliable and feature-rich clipboard manager for GNOME with -over **1M** downloads. - -|Screenshot| - -.. |Screenshot| image:: ./screenshot.png - :width: 400 - :alt: A screenshot of the clipboard manager, showing clipboard history including images - -This extension is also packaged by the community for many popular Linux distros -— search your package manager. - -🧰 Features: ----------------- - -- Highly customizable -- Supports both text and images -- Allows pinning items to top -- Includes a "private" mode -- Has configurable shortcuts -- Keyboard control - -In-Menu Keyboard Controls -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Use arrows to navigate -- :code:`v` to paste directly from menu -- :code:`p` to pin item -- :code:`` to delete an item - -📦 Install from source ----------------- - -Installation via git is performed by cloning the repo into your local gnome-shell extensions directory (usually :code:`~/.local/share/gnome-shell/extensions/`):: - - $ git clone https://github.com/Tudmotu/gnome-shell-extension-clipboard-indicator.git /clipboard-indicator@tudmotu.com - -After cloning the repo, the extension is practically installed yet disabled. In order to enable it, run the following command:: - - $ gnome-extensions enable clipboard-indicator@tudmotu.com - - -✅ GNOME Version Support --------------------------- -Depending on your GNOME version, you will need to install the following -Clipboard Indicator versions: - -* GNOME 45 and above: - - * Use latest version - -* GNOME 42-44 - - * v47 - -* GNOME 40-41 - - * v39 - -* GNOME <40 - - * v37 - -⌨️ Contributing ----------------- -Contributions to this project are welcome. - -Please follow these guidelines when contributing: - -- If you want to contribute code, your best bet is to look for an issue with the label "Up for grabs" -- DO NOT open unsolicited PRs unless they are for updating translations -- Look at the list of previous PRs before you open a PR, if your PR conflicts with another, it will be rejected -- If you have a feature idea, open an issue and discuss it there before implementing. DO NOT open a PR as a platform for discussion - -Note: I have very little time to maintain this project, so expect long (months) of response time. Apologies in advance. diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/confirmDialog.js b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/confirmDialog.js deleted file mode 100644 index 745e912..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/confirmDialog.js +++ /dev/null @@ -1,72 +0,0 @@ -import St from 'gi://St'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import * as ModalDialog from 'resource:///org/gnome/shell/ui/modalDialog.js'; - -export class DialogManager { - #openDialog; - - open (title, message, sub_message, ok_label, cancel_label, callback) { - if (this.#openDialog) return; - this.#openDialog = new ConfirmDialog(title, message + "\n" + sub_message, ok_label, cancel_label, callback); - this.#openDialog.onFinish = () => this.#openDialog = null; - this.#openDialog.open(); - } - - destroy () { - if (this.#openDialog) this.#openDialog.destroy(); - this.#openDialog = null; - } -} - -const ConfirmDialog = GObject.registerClass( - class ConfirmDialog extends ModalDialog.ModalDialog { - - _init(title, desc, ok_label, cancel_label, callback) { - super._init(); - - let main_box = new St.BoxLayout({ - vertical: false - }); - this.contentLayout.add_child(main_box); - - let message_box = new St.BoxLayout({ - vertical: true - }); - main_box.add_child(message_box); - - let subject_label = new St.Label({ - style: 'font-weight: bold', - x_align: Clutter.ActorAlign.CENTER, - text: title - }); - message_box.add_child(subject_label); - - let desc_label = new St.Label({ - style: 'padding-top: 12px', - x_align: Clutter.ActorAlign.CENTER, - text: desc - }); - message_box.add_child(desc_label); - - this.setButtons([ - { - label: cancel_label, - action: () => { - this.close(); - this.onFinish(); - }, - key: Clutter.Escape - }, - { - label: ok_label, - action: () => { - this.close(); - this.onFinish(); - callback(); - } - } - ]); - } - } -); diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/constants.js b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/constants.js deleted file mode 100644 index a2cc96c..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/constants.js +++ /dev/null @@ -1,23 +0,0 @@ -export const PrefsFields = { - HISTORY_SIZE : 'history-size', - PREVIEW_SIZE : 'preview-size', - CACHE_FILE_SIZE : 'cache-size', - CACHE_ONLY_FAVORITE : 'cache-only-favorites', - DELETE : 'enable-deletion', - NOTIFY_ON_COPY : 'notify-on-copy', - CONFIRM_ON_CLEAR : 'confirm-clear', - MOVE_ITEM_FIRST : 'move-item-first', - ENABLE_KEYBINDING : 'enable-keybindings', - TOPBAR_PREVIEW_SIZE : 'topbar-preview-size', - TOPBAR_DISPLAY_MODE_ID : 'display-mode', - DISABLE_DOWN_ARROW : 'disable-down-arrow', - STRIP_TEXT : 'strip-text', - KEEP_SELECTED_ON_CLEAR : 'keep-selected-on-clear', - PASTE_BUTTON : 'paste-button', - PINNED_ON_BOTTOM : 'pinned-on-bottom', - BINDING_TOGGLE_MENU : 'toggle-menu', - BINDING_CLEAR_HISTORY : 'clear-history', - BINDING_PREV_ENTRY : 'prev-entry', - BINDING_NEXT_ENTRY : 'next-entry', - BINDING_PRIVATE_MODE : 'private-mode-binding', -}; diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/extension.js b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/extension.js deleted file mode 100644 index d927076..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/extension.js +++ /dev/null @@ -1,1134 +0,0 @@ -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as AnimationUtils from 'resource:///org/gnome/shell/misc/animationUtils.js'; -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import { Registry, ClipboardEntry } from './registry.js'; -import { DialogManager } from './confirmDialog.js'; -import { PrefsFields } from './constants.js'; -import { Keyboard } from './keyboard.js'; - -const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; - -const INDICATOR_ICON = 'edit-paste-symbolic'; - -let DELAYED_SELECTION_TIMEOUT = 750; -let MAX_REGISTRY_LENGTH = 15; -let MAX_ENTRY_LENGTH = 50; -let CACHE_ONLY_FAVORITE = false; -let DELETE_ENABLED = true; -let MOVE_ITEM_FIRST = false; -let ENABLE_KEYBINDING = true; -let PRIVATEMODE = false; -let NOTIFY_ON_COPY = true; -let CONFIRM_ON_CLEAR = true; -let MAX_TOPBAR_LENGTH = 15; -let TOPBAR_DISPLAY_MODE = 1; //0 - only icon, 1 - only clipboard content, 2 - both -let DISABLE_DOWN_ARROW = false; -let STRIP_TEXT = false; -let KEEP_SELECTED_ON_CLEAR = false; -let PASTE_BUTTON = true; -let PINNED_ON_BOTTOM = false; - -export default class ClipboardIndicatorExtension extends Extension { - enable () { - this.clipboardIndicator = new ClipboardIndicator({ - clipboard: St.Clipboard.get_default(), - settings: this.getSettings(), - openSettings: this.openPreferences, - uuid: this.uuid - }); - - Main.panel.addToStatusArea('clipboardIndicator', this.clipboardIndicator, 1); - } - - disable () { - this.clipboardIndicator.destroy(); - this.clipboardIndicator = null; - } -} - -const ClipboardIndicator = GObject.registerClass({ - GTypeName: 'ClipboardIndicator' -}, class ClipboardIndicator extends PanelMenu.Button { - #refreshInProgress = false; - - destroy () { - this._disconnectSettings(); - this._unbindShortcuts(); - this._disconnectSelectionListener(); - this._clearDelayedSelectionTimeout(); - this.#clearTimeouts(); - this.dialogManager.destroy(); - this.keyboard.destroy(); - - super.destroy(); - } - - _init (extension) { - super._init(0.0, "ClipboardIndicator"); - this.extension = extension; - this.registry = new Registry(extension); - this.keyboard = new Keyboard(); - this._settingsChangedId = null; - this._selectionOwnerChangedId = null; - this._historyLabel = null; - this._buttonText = null; - this._disableDownArrow = null; - - this._shortcutsBindingIds = []; - this.clipItemsRadioGroup = []; - - let hbox = new St.BoxLayout({ - style_class: 'panel-status-menu-box clipboard-indicator-hbox' - }); - - this.hbox = hbox; - - this.icon = new St.Icon({ - icon_name: INDICATOR_ICON, - style_class: 'system-status-icon clipboard-indicator-icon' - }); - - this._buttonText = new St.Label({ - text: _('Text will be here'), - y_align: Clutter.ActorAlign.CENTER - }); - - this._buttonImgPreview = new St.Bin({ - style_class: 'clipboard-indicator-topbar-preview' - }); - - hbox.add_child(this.icon); - hbox.add_child(this._buttonText); - hbox.add_child(this._buttonImgPreview); - this._downArrow = PopupMenu.arrowIcon(St.Side.BOTTOM); - hbox.add(this._downArrow); - this.add_child(hbox); - this._createHistoryLabel(); - this._loadSettings(); - this.dialogManager = new DialogManager(); - this._buildMenu().then(() => { - this._updateTopbarLayout(); - this._setupListener(); - }); - } - - #updateIndicatorContent(entry) { - if (this.preventIndicatorUpdate || (TOPBAR_DISPLAY_MODE !== 1 && TOPBAR_DISPLAY_MODE !== 2)) { - return; - } - - if (!entry || PRIVATEMODE) { - this._buttonImgPreview.destroy_all_children(); - this._buttonText.set_text("...") - } else { - if (entry.isText()) { - this._buttonText.set_text(this._truncate(entry.getStringValue(), MAX_TOPBAR_LENGTH)); - this._buttonImgPreview.destroy_all_children(); - } - else if (entry.isImage()) { - this._buttonText.set_text(''); - this._buttonImgPreview.destroy_all_children(); - this.registry.getEntryAsImage(entry).then(img => { - img.add_style_class_name('clipboard-indicator-img-preview'); - img.y_align = Clutter.ActorAlign.CENTER; - - // icon only renders properly in setTimeout for some arcane reason - this._imagePreviewTimeout = setTimeout(() => { - this._buttonImgPreview.set_child(img); - }, 0); - }); - } - } - } - - async _buildMenu () { - let that = this; - const clipHistory = await this._getCache(); - let lastIdx = clipHistory.length - 1; - let clipItemsArr = that.clipItemsRadioGroup; - - /* This create the search entry, which is add to a menuItem. - The searchEntry is connected to the function for research. - The menu itself is connected to some shitty hack in order to - grab the focus of the keyboard. */ - that._entryItem = new PopupMenu.PopupBaseMenuItem({ - reactive: false, - can_focus: false - }); - that.searchEntry = new St.Entry({ - name: 'searchEntry', - style_class: 'search-entry', - can_focus: true, - hint_text: _('Type here to search...'), - track_hover: true, - x_expand: true, - y_expand: true, - primary_icon: new St.Icon({ icon_name: 'edit-find-symbolic' }) - }); - - that.searchEntry.get_clutter_text().connect( - 'text-changed', - that._onSearchTextChanged.bind(that) - ); - - that._entryItem.add(that.searchEntry); - - that.menu.connect('open-state-changed', (self, open) => { - this._setFocusOnOpenTimeout = setTimeout(() => { - if (open) { - if (this.clipItemsRadioGroup.length > 0) { - that.searchEntry.set_text(''); - global.stage.set_key_focus(that.searchEntry); - } - else { - global.stage.set_key_focus(that.privateModeMenuItem); - } - } - }, 50); - }); - - // Create menu sections for items - // Favorites - that.favoritesSection = new PopupMenu.PopupMenuSection(); - - that.scrollViewFavoritesMenuSection = new PopupMenu.PopupMenuSection(); - this.favoritesScrollView = new St.ScrollView({ - style_class: 'ci-history-menu-section', - overlay_scrollbars: true - }); - this.favoritesScrollView.add_actor(that.favoritesSection.actor); - - that.scrollViewFavoritesMenuSection.actor.add_actor(this.favoritesScrollView); - this.favoritesSeparator = new PopupMenu.PopupSeparatorMenuItem(); - - // History - that.historySection = new PopupMenu.PopupMenuSection(); - - that.scrollViewMenuSection = new PopupMenu.PopupMenuSection(); - this.historyScrollView = new St.ScrollView({ - style_class: 'ci-main-menu-section ci-history-menu-section', - overlay_scrollbars: true - }); - this.historyScrollView.add_actor(that.historySection.actor); - - that.scrollViewMenuSection.actor.add_actor(this.historyScrollView); - - // Add separator - this.historySeparator = new PopupMenu.PopupSeparatorMenuItem(); - - // Add sections ordered according to settings - if (PINNED_ON_BOTTOM) { - that.menu.addMenuItem(that.scrollViewMenuSection); - that.menu.addMenuItem(that.scrollViewFavoritesMenuSection); - } - else { - that.menu.addMenuItem(that.scrollViewFavoritesMenuSection); - that.menu.addMenuItem(that.scrollViewMenuSection); - } - - // Private mode switch - that.privateModeMenuItem = new PopupMenu.PopupSwitchMenuItem( - _("Private mode"), PRIVATEMODE, { reactive: true }); - that.privateModeMenuItem.connect('toggled', - that._onPrivateModeSwitch.bind(that)); - that.privateModeMenuItem.insert_child_at_index( - new St.Icon({ - icon_name: 'security-medium-symbolic', - style_class: 'clipboard-menu-icon', - y_align: Clutter.ActorAlign.CENTER - }), - 0 - ); - that.menu.addMenuItem(that.privateModeMenuItem); - - // Add 'Clear' button which removes all items from cache - this.clearMenuItem = new PopupMenu.PopupMenuItem(_('Clear history')); - this.clearMenuItem.insert_child_at_index( - new St.Icon({ - icon_name: 'user-trash-symbolic', - style_class: 'clipboard-menu-icon', - y_align: Clutter.ActorAlign.CENTER - }), - 0 - ); - this.clearMenuItem.connect('activate', that._removeAll.bind(that)); - - // Add 'Settings' menu item to open settings - this.settingsMenuItem = new PopupMenu.PopupMenuItem(_('Settings')); - this.settingsMenuItem.insert_child_at_index( - new St.Icon({ - icon_name: 'preferences-system-symbolic', - style_class: 'clipboard-menu-icon', - y_align: Clutter.ActorAlign.CENTER - }), - 0 - ); - that.menu.addMenuItem(this.settingsMenuItem); - this.settingsMenuItem.connect('activate', that._openSettings.bind(that)); - - // Empty state section - this.emptyStateSection = new St.BoxLayout({ - style_class: 'clipboard-indicator-empty-state', - vertical: true - }); - this.emptyStateSection.add_child(new St.Icon({ - icon_name: INDICATOR_ICON, - style_class: 'system-status-icon clipboard-indicator-icon', - x_align: Clutter.ActorAlign.CENTER - })); - this.emptyStateSection.add_child(new St.Label({ - text: _('Clipboard is empty'), - x_align: Clutter.ActorAlign.CENTER - })); - - // Add cached items - clipHistory.forEach(entry => this._addEntry(entry)); - - if (lastIdx >= 0) { - that._selectMenuItem(clipItemsArr[lastIdx]); - } - - this.#showElements(); - } - - #hideElements() { - if (this.menu.box.contains(this._entryItem)) this.menu.box.remove_child(this._entryItem); - if (this.menu.box.contains(this.favoritesSeparator)) this.menu.box.remove_child(this.favoritesSeparator); - if (this.menu.box.contains(this.historySeparator)) this.menu.box.remove_child(this.historySeparator); - if (this.menu.box.contains(this.clearMenuItem)) this.menu.box.remove_child(this.clearMenuItem); - if (this.menu.box.contains(this.emptyStateSection)) this.menu.box.remove_child(this.emptyStateSection); - } - - #showElements() { - if (this.clipItemsRadioGroup.length > 0) { - if (this.menu.box.contains(this._entryItem) === false) { - this.menu.box.insert_child_at_index(this._entryItem, 0); - } - if (this.menu.box.contains(this.clearMenuItem) === false) { - this.menu.box.insert_child_below(this.clearMenuItem, this.settingsMenuItem); - } - if (this.menu.box.contains(this.emptyStateSection) === true) { - this.menu.box.remove_child(this.emptyStateSection); - } - - if (this.favoritesSection._getMenuItems().length > 0) { - if (this.menu.box.contains(this.favoritesSeparator) === false) { - this.menu.box.insert_child_above(this.favoritesSeparator, this.scrollViewFavoritesMenuSection.actor); - } - } - else if (this.menu.box.contains(this.favoritesSeparator) === true) { - this.menu.box.remove_child(this.favoritesSeparator); - } - - if (this.historySection._getMenuItems().length > 0) { - if (this.menu.box.contains(this.historySeparator) === false) { - this.menu.box.insert_child_above(this.historySeparator, this.scrollViewMenuSection.actor); - } - } - else if (this.menu.box.contains(this.historySeparator) === true) { - this.menu.box.remove_child(this.historySeparator); - } - } - else if (this.menu.box.contains(this.emptyStateSection) === false) { - this.#renderEmptyState(); - } - } - - #renderEmptyState () { - this.#hideElements(); - this.menu.box.insert_child_at_index(this.emptyStateSection, 0); - } - - /* When text change, this function will check, for each item of the - historySection and favoritesSestion, if it should be visible or not (based on words contained - in the clipContents attribute of the item). It doesn't destroy or create - items. It the entry is empty, the section is restored with all items - set as visible. */ - _onSearchTextChanged () { - let searchedText = this.searchEntry.get_text().toLowerCase(); - - if(searchedText === '') { - this._getAllIMenuItems().forEach(function(mItem){ - mItem.actor.visible = true; - }); - } - else { - this._getAllIMenuItems().forEach(function(mItem){ - let text = mItem.clipContents.toLowerCase(); - let isMatching = text.indexOf(searchedText) >= 0; - mItem.actor.visible = isMatching - }); - } - } - - _truncate (string, length) { - let shortened = string.replace(/\s+/g, ' '); - - let chars = [...shortened] - if (chars.length > length) - shortened = chars.slice(0, length - 1).join('') + '...'; - - return shortened; - } - - _setEntryLabel (menuItem) { - const { entry } = menuItem; - if (entry.isText()) { - menuItem.label.set_text(this._truncate(entry.getStringValue(), MAX_ENTRY_LENGTH)); - } - else if (entry.isImage()) { - this.registry.getEntryAsImage(entry).then(img => { - img.add_style_class_name('clipboard-menu-img-preview'); - if (menuItem.previewImage) { - menuItem.remove_child(menuItem.previewImage); - } - menuItem.previewImage = img; - menuItem.insert_child_below(img, menuItem.label); - }); - } - } - - _findNextMenuItem (currentMenutItem) { - let currentIndex = this.clipItemsRadioGroup.indexOf(currentMenutItem); - - // for only one item - if(this.clipItemsRadioGroup.length === 1) { - return null; - } - - // when focus is in middle of the displayed list - for (let i = currentIndex - 1; i >= 0; i--) { - let menuItem = this.clipItemsRadioGroup[i]; - if (menuItem.actor.visible) { - return menuItem; - } - } - - // when focus is at the last element of the displayed list - let beforeMenuItem = this.clipItemsRadioGroup[currentIndex + 1]; - if(beforeMenuItem.actor.visible){ - return beforeMenuItem; - } - - return null; - } - - #selectNextMenuItem (menuItem) { - let nextMenuItem = this._findNextMenuItem(menuItem); - - if (nextMenuItem) { - nextMenuItem.actor.grab_key_focus(); - } else { - this.privateModeMenuItem.actor.grab_key_focus(); - } - } - - _addEntry (entry, autoSelect, autoSetClip) { - let menuItem = new PopupMenu.PopupMenuItem(''); - - menuItem.menu = this.menu; - menuItem.entry = entry; - menuItem.clipContents = entry.getStringValue(); - menuItem.radioGroup = this.clipItemsRadioGroup; - menuItem.buttonPressId = menuItem.connect('activate', - autoSet => this._onMenuItemSelectedAndMenuClose(menuItem, autoSet)); - menuItem.connect('key-focus-in', () => { - const viewToScroll = menuItem.entry.isFavorite() ? - this.favoritesScrollView : this.historyScrollView; - AnimationUtils.ensureActorVisibleInScrollView(viewToScroll, menuItem); - }); - menuItem.actor.connect('key-press-event', (actor, event) => { - if(event.get_key_symbol() === Clutter.KEY_Delete) { - this.#selectNextMenuItem(menuItem); - this._removeEntry(menuItem, 'delete'); - } - else if (event.get_key_symbol() === Clutter.KEY_p) { - this.#selectNextMenuItem(menuItem); - this._favoriteToggle(menuItem); - } - else if (event.get_key_symbol() === Clutter.KEY_v) { - this.#pasteItem(menuItem); - } - }) - - this._setEntryLabel(menuItem); - this.clipItemsRadioGroup.push(menuItem); - - // Favorite button - let iconfav = new St.Icon({ - icon_name: 'view-pin-symbolic', - style_class: 'system-status-icon' - }); - - let icofavBtn = new St.Button({ - style_class: 'ci-pin-btn ci-action-btn', - can_focus: true, - child: iconfav, - x_align: Clutter.ActorAlign.END, - x_expand: true, - y_expand: true - }); - - menuItem.actor.add_child(icofavBtn); - menuItem.icofavBtn = icofavBtn; - menuItem.favoritePressId = icofavBtn.connect('clicked', - () => this._favoriteToggle(menuItem) - ); - - // Paste button - menuItem.pasteBtn = new St.Button({ - style_class: 'ci-action-btn', - can_focus: true, - child: new St.Icon({ - icon_name: 'edit-paste-symbolic', - style_class: 'system-status-icon' - }), - x_align: Clutter.ActorAlign.END, - x_expand: false, - y_expand: true, - visible: PASTE_BUTTON - }); - - menuItem.pasteBtn.connect('clicked', - () => this.#pasteItem(menuItem) - ); - - menuItem.actor.add_child(menuItem.pasteBtn); - - // Delete button - let icon = new St.Icon({ - icon_name: 'edit-delete-symbolic', //'mail-attachment-symbolic', - style_class: 'system-status-icon' - }); - - let icoBtn = new St.Button({ - style_class: 'ci-action-btn', - can_focus: true, - child: icon, - x_align: Clutter.ActorAlign.END, - x_expand: false, - y_expand: true - }); - - menuItem.actor.add_child(icoBtn); - menuItem.icoBtn = icoBtn; - menuItem.deletePressId = icoBtn.connect('clicked', - () => this._removeEntry(menuItem, 'delete') - ); - - if (entry.isFavorite()) { - this.favoritesSection.addMenuItem(menuItem, 0); - } else { - this.historySection.addMenuItem(menuItem, 0); - } - - if (autoSelect === true) { - this._selectMenuItem(menuItem, autoSetClip); - } - else { - menuItem.setOrnament(PopupMenu.Ornament.NONE); - } - - this.#showElements(); - } - - _favoriteToggle (menuItem) { - menuItem.entry.favorite = menuItem.entry.isFavorite() ? false : true; - this._moveItemFirst(menuItem); - this._updateCache(); - this.#showElements(); - } - - _confirmRemoveAll () { - const title = _("Clear all?"); - const message = _("Are you sure you want to delete all clipboard items?"); - const sub_message = _("This operation cannot be undone."); - - this.dialogManager.open(title, message, sub_message, _("Clear"), _("Cancel"), () => { - this._clearHistory(); - } - ); - } - - _clearHistory () { - // Don't remove pinned items - this.historySection._getMenuItems().forEach(mItem => { - if (KEEP_SELECTED_ON_CLEAR === false || !mItem.currentlySelected) { - this._removeEntry(mItem, 'delete'); - } - }); - this._showNotification(_("Clipboard history cleared")); - } - - _removeAll () { - if (PRIVATEMODE) return; - var that = this; - - if (CONFIRM_ON_CLEAR) { - that._confirmRemoveAll(); - } else { - that._clearHistory(); - } - } - - _removeEntry (menuItem, event) { - let itemIdx = this.clipItemsRadioGroup.indexOf(menuItem); - - if(event === 'delete' && menuItem.currentlySelected) { - this.#clearClipboard(); - } - - menuItem.destroy(); - this.clipItemsRadioGroup.splice(itemIdx,1); - - if (menuItem.entry.isImage()) { - this.registry.deleteEntryFile(menuItem.entry); - } - - this._updateCache(); - this.#showElements(); - } - - _removeOldestEntries () { - let that = this; - - let clipItemsRadioGroupNoFavorite = that.clipItemsRadioGroup.filter( - item => item.entry.isFavorite() === false); - - const origSize = clipItemsRadioGroupNoFavorite.length; - - while (clipItemsRadioGroupNoFavorite.length > MAX_REGISTRY_LENGTH) { - let oldestNoFavorite = clipItemsRadioGroupNoFavorite.shift(); - that._removeEntry(oldestNoFavorite); - - clipItemsRadioGroupNoFavorite = that.clipItemsRadioGroup.filter( - item => item.entry.isFavorite() === false); - } - - if (clipItemsRadioGroupNoFavorite.length < origSize) { - that._updateCache(); - } - } - - _onMenuItemSelected (menuItem, autoSet) { - for (let otherMenuItem of menuItem.radioGroup) { - let clipContents = menuItem.clipContents; - - if (otherMenuItem === menuItem && clipContents) { - menuItem.setOrnament(PopupMenu.Ornament.DOT); - menuItem.currentlySelected = true; - if (autoSet !== false) - this.#updateClipboard(menuItem.entry); - } - else { - otherMenuItem.setOrnament(PopupMenu.Ornament.NONE); - otherMenuItem.currentlySelected = false; - } - } - } - - _selectMenuItem (menuItem, autoSet) { - this._onMenuItemSelected(menuItem, autoSet); - this.#updateIndicatorContent(menuItem.entry); - } - - _onMenuItemSelectedAndMenuClose (menuItem, autoSet) { - for (let otherMenuItem of menuItem.radioGroup) { - let clipContents = menuItem.clipContents; - - if (menuItem === otherMenuItem && clipContents) { - menuItem.setOrnament(PopupMenu.Ornament.DOT); - menuItem.currentlySelected = true; - if (autoSet !== false) - this.#updateClipboard(menuItem.entry); - } - else { - otherMenuItem.setOrnament(PopupMenu.Ornament.NONE); - otherMenuItem.currentlySelected = false; - } - } - - menuItem.menu.close(); - } - - _getCache () { - return this.registry.read(); - } - - #addToCache (entry) { - const entries = this.clipItemsRadioGroup - .map(menuItem => menuItem.entry) - .filter(entry => CACHE_ONLY_FAVORITE == false || entry.isFavorite()) - .concat([entry]); - this.registry.write(entries); - } - - _updateCache () { - const entries = this.clipItemsRadioGroup - .map(menuItem => menuItem.entry) - .filter(entry => CACHE_ONLY_FAVORITE == false || entry.isFavorite()); - - this.registry.write(entries); - } - - async _onSelectionChange (selection, selectionType, selectionSource) { - if (selectionType === Meta.SelectionType.SELECTION_CLIPBOARD) { - this._refreshIndicator(); - } - } - - async _refreshIndicator () { - if (PRIVATEMODE) return; // Private mode, do not. - if (this.#refreshInProgress) return; - this.#refreshInProgress = true; - - try { - const result = await this.#getClipboardContent(); - - if (result) { - for (let menuItem of this.clipItemsRadioGroup) { - if (menuItem.entry.equals(result)) { - this._selectMenuItem(menuItem, false); - - if (!menuItem.entry.isFavorite() && MOVE_ITEM_FIRST) { - this._moveItemFirst(menuItem); - } - - return; - } - } - - this.#addToCache(result); - this._addEntry(result, true, false); - this._removeOldestEntries(); - if (NOTIFY_ON_COPY) { - this._showNotification(_("Copied to clipboard"), notif => { - notif.addAction(_('Cancel'), this._cancelNotification); - }); - } - } - } - catch (e) { - console.error('Clipboard Indicator: Failed to refresh indicator'); - console.error(e); - } - finally { - this.#refreshInProgress = false; - } - } - - _moveItemFirst (item) { - this._removeEntry(item); - this._addEntry(item.entry, item.currentlySelected, false); - this._updateCache(); - } - - _findItem (text) { - return this.clipItemsRadioGroup.filter( - item => item.clipContents === text)[0]; - } - - _getCurrentlySelectedItem () { - return this.clipItemsRadioGroup.find(item => item.currentlySelected); - } - - _getAllIMenuItems () { - return this.historySection._getMenuItems().concat(this.favoritesSection._getMenuItems()); - } - - _setupListener () { - const metaDisplay = Shell.Global.get().get_display(); - const selection = metaDisplay.get_selection(); - this._setupSelectionTracking(selection); - } - - _setupSelectionTracking (selection) { - this.selection = selection; - this._selectionOwnerChangedId = selection.connect('owner-changed', (selection, selectionType, selectionSource) => { - this._onSelectionChange(selection, selectionType, selectionSource); - }); - } - - _openSettings () { - this.extension.openSettings(); - } - - _initNotifSource () { - if (!this._notifSource) { - this._notifSource = new MessageTray.Source('ClipboardIndicator', - INDICATOR_ICON); - this._notifSource.connect('destroy', () => { - this._notifSource = null; - }); - Main.messageTray.add(this._notifSource); - } - } - - _cancelNotification () { - if (this.clipItemsRadioGroup.length >= 2) { - let clipSecond = this.clipItemsRadioGroup.length - 2; - let previousClip = this.clipItemsRadioGroup[clipSecond]; - this.#updateClipboard(previousClip.entry); - previousClip.setOrnament(PopupMenu.Ornament.DOT); - previousClip.icoBtn.visible = false; - previousClip.currentlySelected = true; - } else { - this.#clearClipboard(); - } - let clipFirst = this.clipItemsRadioGroup.length - 1; - this._removeEntry(this.clipItemsRadioGroup[clipFirst]); - } - - _showNotification (message, transformFn) { - const dndOn = () => - !Main.panel.statusArea.dateMenu._indicator._settings.get_boolean( - 'show-banners', - ); - if (PRIVATEMODE || dndOn()) { - return; - } - - let notification = null; - - this._initNotifSource(); - - if (this._notifSource.count === 0) { - notification = new MessageTray.Notification(this._notifSource, message); - } - else { - notification = this._notifSource.notifications[0]; - notification.update(message, '', { clear: true }); - } - - if (typeof transformFn === 'function') { - transformFn(notification); - } - - notification.setTransient(true); - this._notifSource.showNotification(notification); - } - - _createHistoryLabel () { - this._historyLabel = new St.Label({ - style_class: 'ci-notification-label', - text: '' - }); - - global.stage.add_actor(this._historyLabel); - - this._historyLabel.hide(); - } - - togglePrivateMode () { - this.privateModeMenuItem.toggle(); - } - - _onPrivateModeSwitch () { - let that = this; - PRIVATEMODE = this.privateModeMenuItem.state; - // We hide the history in private ModeTypee because it will be out of sync (selected item will not reflect clipboard) - this.scrollViewMenuSection.actor.visible = !PRIVATEMODE; - this.scrollViewFavoritesMenuSection.actor.visible = !PRIVATEMODE; - // If we get out of private mode then we restore the clipboard to old state - if (!PRIVATEMODE) { - let selectList = this.clipItemsRadioGroup.filter((item) => !!item.currentlySelected); - - if (selectList.length) { - this._selectMenuItem(selectList[0]); - } else { - // Nothing to return to, let's empty it instead - this.#clearClipboard(); - } - - this.#getClipboardContent().then(entry => { - if (!entry) return; - this.#updateIndicatorContent(entry); - }).catch(e => console.error(e)); - - this.hbox.remove_style_class_name('private-mode'); - this.#showElements(); - } else { - this.hbox.add_style_class_name('private-mode'); - this.#updateIndicatorContent(null); - this.#hideElements(); - } - } - - _loadSettings () { - this._settingsChangedId = this.extension.settings.connect('changed', - this._onSettingsChange.bind(this)); - - this._fetchSettings(); - - if (ENABLE_KEYBINDING) - this._bindShortcuts(); - } - - _fetchSettings () { - const { settings } = this.extension; - MAX_REGISTRY_LENGTH = settings.get_int(PrefsFields.HISTORY_SIZE); - MAX_ENTRY_LENGTH = settings.get_int(PrefsFields.PREVIEW_SIZE); - CACHE_ONLY_FAVORITE = settings.get_boolean(PrefsFields.CACHE_ONLY_FAVORITE); - DELETE_ENABLED = settings.get_boolean(PrefsFields.DELETE); - MOVE_ITEM_FIRST = settings.get_boolean(PrefsFields.MOVE_ITEM_FIRST); - NOTIFY_ON_COPY = settings.get_boolean(PrefsFields.NOTIFY_ON_COPY); - CONFIRM_ON_CLEAR = settings.get_boolean(PrefsFields.CONFIRM_ON_CLEAR); - ENABLE_KEYBINDING = settings.get_boolean(PrefsFields.ENABLE_KEYBINDING); - MAX_TOPBAR_LENGTH = settings.get_int(PrefsFields.TOPBAR_PREVIEW_SIZE); - TOPBAR_DISPLAY_MODE = settings.get_int(PrefsFields.TOPBAR_DISPLAY_MODE_ID); - DISABLE_DOWN_ARROW = settings.get_boolean(PrefsFields.DISABLE_DOWN_ARROW); - STRIP_TEXT = settings.get_boolean(PrefsFields.STRIP_TEXT); - KEEP_SELECTED_ON_CLEAR = settings.get_boolean(PrefsFields.KEEP_SELECTED_ON_CLEAR); - PASTE_BUTTON = settings.get_boolean(PrefsFields.PASTE_BUTTON); - PINNED_ON_BOTTOM = settings.get_boolean(PrefsFields.PINNED_ON_BOTTOM); - - } - - async _onSettingsChange () { - var that = this; - - // Load the settings into variables - that._fetchSettings(); - - // Remove old entries in case the registry size changed - that._removeOldestEntries(); - - // Re-set menu-items lables in case preview size changed - this._getAllIMenuItems().forEach(function (mItem) { - that._setEntryLabel(mItem); - mItem.pasteBtn.visible = PASTE_BUTTON; - }); - - //update topbar - this._updateTopbarLayout(); - that.#updateIndicatorContent(await this.#getClipboardContent()); - - // Bind or unbind shortcuts - if (ENABLE_KEYBINDING) - that._bindShortcuts(); - else - that._unbindShortcuts(); - } - - _bindShortcuts () { - this._unbindShortcuts(); - this._bindShortcut(PrefsFields.BINDING_CLEAR_HISTORY, this._removeAll); - this._bindShortcut(PrefsFields.BINDING_PREV_ENTRY, this._previousEntry); - this._bindShortcut(PrefsFields.BINDING_NEXT_ENTRY, this._nextEntry); - this._bindShortcut(PrefsFields.BINDING_TOGGLE_MENU, this._toggleMenu); - this._bindShortcut(PrefsFields.BINDING_PRIVATE_MODE, this.togglePrivateMode); - } - - _unbindShortcuts () { - this._shortcutsBindingIds.forEach( - (id) => Main.wm.removeKeybinding(id) - ); - - this._shortcutsBindingIds = []; - } - - _bindShortcut (name, cb) { - var ModeType = Shell.hasOwnProperty('ActionMode') ? - Shell.ActionMode : Shell.KeyBindingMode; - - Main.wm.addKeybinding( - name, - this.extension.settings, - Meta.KeyBindingFlags.NONE, - ModeType.ALL, - cb.bind(this) - ); - - this._shortcutsBindingIds.push(name); - } - - _updateTopbarLayout () { - if(TOPBAR_DISPLAY_MODE === 0){ - this.icon.visible = true; - this._buttonText.visible = false; - } - if(TOPBAR_DISPLAY_MODE === 1){ - this.icon.visible = false; - this._buttonText.visible = true; - } - if(TOPBAR_DISPLAY_MODE === 2){ - this.icon.visible = true; - this._buttonText.visible = true; - } - if(!DISABLE_DOWN_ARROW) { - this._downArrow.visible = true; - } else { - this._downArrow.visible = false; - } - } - - _disconnectSettings () { - if (!this._settingsChangedId) - return; - - this.extension.settings.disconnect(this._settingsChangedId); - this._settingsChangedId = null; - } - - _disconnectSelectionListener () { - if (!this._selectionOwnerChangedId) - return; - - this.selection.disconnect(this._selectionOwnerChangedId); - } - - _clearDelayedSelectionTimeout () { - if (this._delayedSelectionTimeoutId) { - clearInterval(this._delayedSelectionTimeoutId); - } - } - - _selectEntryWithDelay (entry) { - let that = this; - that._selectMenuItem(entry, false); - - that._delayedSelectionTimeoutId = setTimeout(function () { - that._selectMenuItem(entry); //select the item - that._delayedSelectionTimeoutId = null; - }, DELAYED_SELECTION_TIMEOUT); - } - - _previousEntry () { - if (PRIVATEMODE) return; - let that = this; - - that._clearDelayedSelectionTimeout(); - - this._getAllIMenuItems().some(function (mItem, i, menuItems){ - if (mItem.currentlySelected) { - i--; //get the previous index - if (i < 0) i = menuItems.length - 1; //cycle if out of bound - let index = i + 1; //index to be displayed - that._showNotification(index + ' / ' + menuItems.length + ': ' + menuItems[i].entry.getStringValue()); - if (MOVE_ITEM_FIRST) { - that._selectEntryWithDelay(menuItems[i]); - } - else { - that._selectMenuItem(menuItems[i]); - } - return true; - } - return false; - }); - } - - _nextEntry () { - if (PRIVATEMODE) return; - let that = this; - - that._clearDelayedSelectionTimeout(); - - this._getAllIMenuItems().some(function (mItem, i, menuItems){ - if (mItem.currentlySelected) { - i++; //get the next index - if (i === menuItems.length) i = 0; //cycle if out of bound - let index = i + 1; //index to be displayed - that._showNotification(index + ' / ' + menuItems.length + ': ' + menuItems[i].entry.getStringValue()); - if (MOVE_ITEM_FIRST) { - that._selectEntryWithDelay(menuItems[i]); - } - else { - that._selectMenuItem(menuItems[i]); - } - return true; - } - return false; - }); - } - - _toggleMenu () { - this.menu.toggle(); - } - - #pasteItem (menuItem) { - this.menu.close(); - const currentlySelected = this._getCurrentlySelectedItem(); - this.preventIndicatorUpdate = true; - this.#updateClipboard(menuItem.entry); - this._pastingKeypressTimeout = setTimeout(() => { - if (this.keyboard.purpose === Clutter.InputContentPurpose.TERMINAL) { - this.keyboard.press(Clutter.KEY_Control_L); - this.keyboard.press(Clutter.KEY_Shift_L); - this.keyboard.press(Clutter.KEY_Insert); - this.keyboard.release(Clutter.KEY_Insert); - this.keyboard.release(Clutter.KEY_Shift_L); - this.keyboard.release(Clutter.KEY_Control_L); - } - else { - this.keyboard.press(Clutter.KEY_Shift_L); - this.keyboard.press(Clutter.KEY_Insert); - this.keyboard.release(Clutter.KEY_Insert); - this.keyboard.release(Clutter.KEY_Shift_L); - } - - this._pastingResetTimeout = setTimeout(() => { - this.preventIndicatorUpdate = false; - this.#updateClipboard(currentlySelected.entry); - }, 50); - }, 50); - } - - #clearTimeouts () { - if (this._imagePreviewTimeout) clearTimeout(this._imagePreviewTimeout); - if (this._setFocusOnOpenTimeout) clearTimeout(this._setFocusOnOpenTimeout); - if (this._pastingKeypressTimeout) clearTimeout(this._pastingKeypressTimeout); - if (this._pastingResetTimeout) clearTimeout(this._pastingResetTimeout); - } - - #clearClipboard () { - this.extension.clipboard.set_text(CLIPBOARD_TYPE, ""); - this.#updateIndicatorContent(null); - } - - #updateClipboard (entry) { - this.extension.clipboard.set_content(CLIPBOARD_TYPE, entry.mimetype(), entry.asBytes()); - this.#updateIndicatorContent(entry); - } - - async #getClipboardContent () { - const mimetypes = [ - 'text/plain;charset=utf-8', - 'image/gif', - 'image/png', - 'image/jpg', - 'image/jpeg', - 'image/webp', - 'image/svg+xml', - 'text/html', - ]; - - for (let type of mimetypes) { - let result = await new Promise(resolve => this.extension.clipboard.get_content(CLIPBOARD_TYPE, type, (clipBoard, bytes) => { - if (bytes === null || bytes.get_size() === 0) { - resolve(null); - return; - } - - const entry = new ClipboardEntry(type, bytes.get_data(), false); - if (entry.isImage()) { - this.registry.writeEntryFile(entry); - } - resolve(entry); - })); - - if (result) return result; - } - - return null; - } -}); diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/keyboard.js b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/keyboard.js deleted file mode 100644 index 6ec9baa..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/keyboard.js +++ /dev/null @@ -1,41 +0,0 @@ -import Clutter from 'gi://Clutter'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -export class Keyboard { - #device; - #contentPurpose; - - constructor () { - let seat = Clutter.get_default_backend().get_default_seat(); - this.#device = seat.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE); - - Main.inputMethod.connectObject('notify::content-purpose', (method) => { - this.#contentPurpose = method.content_purpose; - }, this); - } - - destroy () { - Main.inputMethod.disconnectObject(this); - this.#device.run_dispose(); - } - - #notify (key, state) { - this.#device.notify_keyval( - Clutter.get_current_event_time() * 1000, - key, - state - ); - } - - get purpose () { - return this.#contentPurpose; - } - - press (key) { - this.#notify(key, Clutter.KeyState.PRESSED); - } - - release (key) { - this.#notify(key, Clutter.KeyState.RELEASED); - } -} diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ar/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ar/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 6bbca1efae9f42ca59bf2fe7600537591d981600..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2308 zcmai!+fN)-9LG;>>t(f7>#g;Y9wR33Fx!P%LKY}eY%PgYg!T3~%pP{f%*=p1W@CdjF-Vc5X9tA%GQ{Xl57`O^P4%Wd_;1A#v z;4k1K;2$8x`3r0V4WA?=Hx}pTS4L zKf$NLV@UQ4*am)xp8CKsoHtQC#XW>(sQ%*(o&qUeTZ7#o<+%)!E)(EO;Bw=<0aBbF z!2$3$@Hz1G1B`WnyXquoHG2#TWf+~QHhL%~QZdM4^a1uC%Ks1+&FLf->5lQ3Isx;L2BZ^d z*?b;uZW^Tdv%ygC8Cm90xv`nHgP6yX=Y=O?!EMjuj^~ypq#fqD8w)=gU>9UuWJ7k~ z2#*bU!VZ()WIWK=7TqY8;S5eq-ys>qB8U&%G;9zbAw-@H$&xGblzcxUyPU+~!sv?lDCWq93a*s>3A~e&+$q|j?Z7bNZeZLd zQ2J;nrd%;?GVu16O-J%ZmZL_X(a@c;A&D>Zf{h8E>X=-5j1p)>2#XCTeQstBg*}cM&$>P#~RLC??3|-ljVg#`ofBe z!t*Q?Bm%m&_T{(SAWwzMFf}GhGK{T}sNm+U3*|y&;`S{DOH<}tD?@0oDp)TmbuZO^(SLqE#$pk$6we^)P0w*Bn^f3cr;cJ!v+ zvtAbg4UM`Ql_KxPyepkacc++M(hFRz>P1!Kx}s{>&Z{kRqvtu!b-hC8n`&FnaN*bJ!SpL^)i=g?oi)S3)mX!+ zqHgNtB-jqpESMWr)64qm!4!8Cylc9`ThX{O4*zXM85Uu%$@Q#WxyNQtZBcjBLaU>e zWl{+=SYj8shU+|YE|9QOZ359SG#xv*W@!w z^iQUgRDuW?Dny?r(Yap2%PLF5ds{D=)R4GBk|8z9t#a5_V7-{U#8->(Xxk)!8@|Iv z_A}UQ?rW;&VD~i|TW9#Ugr4SAO|3N&A~IsHVGcJKOsb}&Mi2WD&7%Q6vqcBU*@BwKoR2W0v`c?0iOi_07X~bsnmnOW1z?{fer9^@Hwyziu^_J zVeoxWL;D__`Pe8GM4Lk|n0MCFwgHM3JgZuFLH+V1B0nWt#1bhno7}Vf3a0&bs zd>s4>yc;})&nfT>xD37ku7JJy{sepg>yPIA3=}(Gf)f9apy=NOp9TK}2|Rg^QV6Ra zQm51N|B|EFlOcJFt_*}<56S(0OoUetn5oBI_||ouuLY8?)I{ndwS{Y?Hhmnct&B~e zu`QzyhgjKS;7v$r%e%-f{%2<{Ly2f`sb;B@zt5 z_->UCIFKJwGB&{^kwZz=!9qa;6I3tozU6~jnU;@aR%R!@D(8lJ!S0*Ll>3y`9>-|i zs8oAne?ZPhJG6<3);q#4@x`I)OAH4#%V@wf=D@1&N281>j$wpdrTT}(>_pNjkzX=y zHk<0*v5EDLm_8P%zsyP0+o^sBNx)Z!M$YG~%Q0t}hCg<)trw-y)}<1c4~y7vH>+CqpQtNq6ZKTy^t9iDe&gFx2dc9Pe zl}!z0x2}FZdz02=c#Te;K@}=sgW=FT#+Y$FE zAGcILccZ#^>ITOpkES=Ifp&d92rS}>3DYlTuO87O9$Xa!tAc~|K`pErDx?$2%49Z9 zOk$_k(GCmcm4y$37M-c05uhYpp?V^ia|~Rn9bY0Es+?IgMr{pA)#(M*&FWhvQ=q5q z6^1UE531=mC}^Hn(Ma}ak?D7;TPE;etJygrYBH2?KxDVBex)u})34Ey;!qB5&+i|1 C%C{H* diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/cs/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/cs/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 112a8606305550325a567449d0eb0c29afa62694..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2125 zcmZvcO>7%Q6vu}WzFa=qLis9`5#=MLTH}NsDz^}5T9ioSLx~AeBo5=ZrwXaPY|I%><$!tsgt#EC96;j#*6Sn{tZe^wcHevRfB%{B zog-tPGhEM=-@n0^@%`x@{NPFsFm@XJ2pj{if%k)7f%k#mfEDlt_z0MThru7fXTV>; z$H9NVhrz@54(l8TU&8nVNcl713*a(Hc@}&W+yp7_3P>8az~{m5zz4x!!56_lK*~D= zku?8nAP3KZkAWY8Pl7S{6!BO|fdXl$vk+&$tU}MoQuzOK` z@`Ch|$Fwe3&Y~|`Te?UK=_QXx*TK;ZNFI@H_D(8!*JRvg<;{lBjyuBx8A&I(h$8Ms zDrp*#23$EA+bMS5xR6Z??aPQwM^dE2UkaWoZ$o9BNxK-0a;J@UQoDUm${5r~2^p|y zlPDR`c}eSQ48+vLzXlj=*eaF4EL& z>@Qiq+z8>9O@t2{Q9PiOxS_B-P02%_QDz{aH>}=+JhXt{+r$wBx`Mhr<8Dwb6&$maxRBC5aI*y?B;5zT{5dGqPG*rhf zFuutvl2d@q}cU5|5mFu99J$<(CUYH5{UJ|^^-W_ zJ=07@&)`tiEO>IRn-$AZILjCPGg1B&b%V0(oz3!T91`did8V%!CKm|Za9zzWOm0vlOa*%1sUYr5Zb7h7F5sjl8} zHk$Ycc$LI>FfnLMyh*YrE@rM?jNS|$yc-Xic=h{wnq9=s^nALe-;eKmuWEkVyX!N7 z>jm8VaQ}__HQYb$z!$C$b_#J6RNyY~I`{zi1$aOB71#j31s?@(f=_@yfX{(HgA?E% z;3MFU`^IthfcvqY0NMW-_%b*TvR@4D0Y3)W?^BTVeGa||Zh{YizkqCi8|1wIfD+sd zv5$cVz^B1B_zd_in4&ffwy^#QMQ}Yk@wFS=4RYKGkp1_8kAsIm&NB<{2d~uYkH9Cf zz7FCezQfl6@OzN;+y-9-{{-28;z1$yf)U8|odT!8i{L?U2y!34244qnf~@;jkmv9h z$bFcE$d|xHko6=WkBn#X6mIt6{9Fs`NBU}h+)KWA-UubouBuL8>tcP}3$BYbvrde! z>LbsRujg^|+@9q{eLZ~Vp(fWM<~+%vD`ipE4+CX`3{ECwD3Daf$k^z9*D0S!9VjnO ziqkG+VqV#pjF>m1{P>%VPu7o_E`swztnT>EI~&M`yMC!{5Fa5Z5%aFEDdFT>8O6DA z9J#7DNG!$9iel@K-z83BE%dV#zwpg9g2Mi=PAAdw9UE|hr}?_5vDner-zVIj4x z+`5py;%QyepvoX8w{51zZ(Lc_fmXa;S7=G@5)zjvXB~+fSgE{sgS$i4F9#X=RrFPi zHhNcDlm=O1l|s-qEyQXDH|v7#=~%IBiBIhML(yUR1C8EyNoM3pbkHp6`sBxkv9fUF zw+QPjHATmzsX;T)keqBOI>Y|hmD^OH!Ex4XHpP`pRpTu<_kX(JuAz6)QW9N8gCM3Y z8<(i>e2A8dR438tGA*Kx!_O-hqf6)+8$}D~NL$XdW?E6}t!U;=Ienx(Gkp;2R^z-X zLe%lf7Diz+wB<#JmS;5;IpoU|whSBOk4(4TIF;r~n`Z3tx8Y^eQl%7iNabz0KxHW6 zOrAjTc0dXR`cu~kFneR`b8|+OqqbL_R<% zEqk8EOykURIGy4r98#UjcdFK*o~;b$&`Mc#gV3@{5yuq^I3FbE)~Y{*H9ja~X?}Do zUQ0(eY^qaCDMyk!yQC==R3Vqij&8}(X0HcPhtVUW2~)D;e-k80x$B2ynad6S!{^$5 U|KuBS#u@15S>D_0EwOF!FWZe;I{*Lx diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/el/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/el/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index d0c2ca18f8aeec06b52a6c42e23513eca9a4329c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1266 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 ZTtd#$L8RY4{t5~VzrpcWCH22r{{zNrZFB$t diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/eu/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/eu/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index dab2f1504d7952c47ab9406395ea380ba649f429..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2031 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 AbpQYW diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fi/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fi/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 964a92195f9fe551a24ebe3b611b4b7753d1f66b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1092 zcmYk4&u<$=6vw9!ei>+KdnlDadKH&MWt?>?XyY_hA*3PDl&EnLt<=NR`?7xC@yu#w zHm!mG0de5U$tSp?NSuA*!e4-T(JyI@oE7;J&VMZ5;j!vARz{}p@_{_l(UAK*Foe}g~3p2IG{ zfAp$SAAuwAeeh?n>GK=d6;|p5q^DNjaAPVg=I0U4{T7#K%=_?6B zJ7Ie4g7=Yb4&k?p;Aiet+sWK*DW!cVw@~Yf+7zsNY(`y*wI2!Hw7xV}q8FD$;~|;b zh4*+7G^wlD?)%YcDU|N*?ropGPp6%=w!BLit?rF0=uVjQYGsYM4QhrPIc+}Z-O)Er z^BVbw9Q3y9`y4~<(v2sQTKl#R#_BshjAEBuHFM+U+6K)ZH82DYC8S3A8-oP?kKLPFB=*&en=!car_E wjFQF}wOFG*!+`1%f9l?JGEPt|cGPHyIBKTGaE#_8x>|`?p9~%0tCf)QKL-po%m4rY diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fr_FR/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/fr_FR/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 013809d74c0cf511764156302a7b646f1662ff13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1971 zcmZXUO>Epm6vqb|z7`6le3dUT60MS`@@A8^sM<6QX_}TuNmw>Z;f7}Ix9dUnj2VxU zrb0a;A#O-WzzK;%yPS%|0SSf9^DY48nj3j6@PAN&Zs5BwNxfS-bg!7stb!LPw*!4iA| z{0)2r{0n3||ANQCLx<}9GvG@Yp8|Q`Huxx*g1qm2@I~-L@Imkf$m?!_?C&Q~g1>@~ zf&YL{gNNbl8Spr`f}GBQGZlW2pi&kD%#55VWa z>)%;PHda=M|s3kxF;8D z&2{EjCKu;%_r>)WD~{xzEo5GdUv`!8(pwo(LY|~b5*a2s>s#d_sXe9nvbbPtXqgA#t%BK{5_4nJ!03Il}Sr$YC^Y7X!OwWULA=*3dNN zi13Gi(~eNYmQDNkZ-D8rYM=5ZJnx5rQ%b538y0n?q7o&URyf7wjRNhozh(B0=?o6S zaugv5LOa89hSoxg+eL=Al;ebpy03DHs4N>Us^XLAz-C(B^aw+&4A5BU9`pzu?6dL< zJ|8R}+D(&~VXbGyDmoLrTK!8%?8yiPDZhd-iA)M;gGQTJoeNcE9Lm-WhrF&y9cr0z QL_Al`bJtDw{7;$x0BDUA#Q*>R diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/hu/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/hu/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index bb2c2dfab1983bbdc652d583e79309ee3091b4d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2127 zcmZvcPiz}S6vn4eC^ZnEE&o9bsFm8nx^^fixP;Jz6r$o18dKoL*dDL9o}IB~#tvSA zgt#CC9CDx%;uH?3K2)Ma@~J{XqudY|xPpKy;s8S8zyZFucG|Qs^6byEJMYc+zS-Fy z_w4+bq1})E0Q#Tk2hhLSfeYFj*D-b!6yQ$q9C#!6DR=|;8CU?%gSUbk;2q%C;Jx5? z;9l@I@D^~#_2WEK;C_tvf)qakJ_Ig+6xRT!z_&q)`w%33pMVd7Bk(5hdywY;0MfdD zfgIcovA2PT!Mnf;csKYmcmlO0;1P_!KoPY5PaxIxD@b|&0QZ1@gA_l7hcrF_a&QLR z2fhwceHuhc_AYoBd=I=C{1SWw{0b!9KZCo#e?Y2h7Y0v(`@jf11ybE_fd{}3K&ty9 zNO``UjDH7d&!!-DKX@3VErVQkCpy(ieo!s9qhq;TAFWA^Vv&NuuG}Z!a-%wTqf>q4 zE$PAb;R*!*af4#)PCEY$sFWI3fW`}rkltn zEq-}L_QE(1Ur92_mKsL0s_DyI2u<{D33Rz=d1<+W=7vu&>6CoabF2mhr+R4}&rFLq z+QNzkCOV$zJgg4s%U1Rixtg!Q4_=vbX#B+V+$7PmP5J_sq^2p^X_=CardicoSZh|d zr<^=oZNo3u6%E*EO;4jV$YLwf`$Wf%t+WxQjZa!hLy&BaU&C|jye+L{ zHJHUsSK9H!hR_J4r$}qGEV7!3V+Au{NGf%Y)dt;hDB0v-aHCx;7TK$9k#Db~wXbr) zoP~GMQZqUOgCM5D3#Vn*SRYkgoHV2PUhJZp!R_UjqSNqGss-A?-1S86AsnJe>1 zPfOZpQ8!Ez`%vLC^~4umi=LO7>?NVgMm7`Ar;A66<-)S+S)rm6#-^^qbvGZn+390^ z{CD=C<`2*E@}Xk|HlJkPxW{Dh=D*YU*Cc4?d z`>?sjs$m#AY%~Rhp=06PI3~}68*+{z-5J#vSLb(GSVyL%4vy2Ja+_;-5!C=+iPU7V@QC4^1O+MKvV7FTRkM>} z)R(>^Gn8}^=dFYD2DRgCT=166bGfkIuM5h&xu(M~lO8gLmOeQLJCm?OV?jtnM=z|? zl#M1k&Xq)#Fyv{^L&yf#gK$A{sUV9Fv=#c8JG!)+UR**+}UF&5&s(j?yVmWgp1~04woM%{g2!K0_EU(ssI20 diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/it/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/it/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 261e9a36635e8e2bc9c7eee89f6f4679c7119e52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2047 zcmZ9MOKclO7{>=%9yOFlp}Y#>Lu%C+Sl0=Uq)tO<9)(DxxVBrkj&~>aRI@Xio!OXF z9JqjlxF94XjtC^+2s!tbTd%zq4yeaoIC7xk|E)Jp)0M}+eSGh4zWM9e;qL{mm#|*O zx`TBJ>-q!u!_|IJh_}H@;9>A9@L}*9@FDO!um=7B9tD2}p9cQ`Uj%o-XTU$f$H9L< zwsRLe2_8B$)}I1j#q(Pr>vh2=z!YS?&%sx~ufa#bUqP1p9b|tuKmu=pPlEq}&w)qb z?0N7c*hNm~z$H9?i{RPLP4E%$R>j*O+q(m@{#}scKaQl2gY}Aw;0Zim1|cFg!PmhN z$o_u<3ETlsfj6u7|AK7)2%Ofz6Cmfe3UdA(@EDkbZ-QTf9RCi;`Q8AzSGPfK5&M1? zi(_TGoYPZSa8uTqZS%!CP!T9g86PmY*xwN>&hrHZ?SV`ap$Q8FL@v+!bd zJJde7d>c=Dy35W6Wy3vhDjC>^36+RtmuZ!-^NC0C;n)s!^))5dVrRv=+frp9EEt9g z$VhGkm6J!zanKODs6Gn>Z;0Sxk@oS;ZBRUvxr`y`N!wDbkI>t>+R|!NdZ4L&nfmyP zD|}_Bo$D=$lB6zCqN7rdV>Cobd?sU5DtCoN^zbaYDgg_xlH9_!B|=-@>iI3Ry9P=4F(4JBIi`uLiDz?u_{->qlWRY z(P)TIhO+FSXWs`BbyrcIXf27Zpaux0MYWE~TpprzKhR0ER1AF7b9mkUIO?D*EEKIE z=@!j2r{|*PJJIwkHP5zYX5VPeG@G@Lqz_Rqm)0AJez&OO`fz!!&#H~Hv+oa5sZAqx z>3fj1gF+5e)KfBT(N&$M+YKMXMbP_l6R{SWTw7mTU)_&(y3wpv+bH7XTV=J+WJYQ` zU$)n)uyDC|A)4ElgcWZ4^%E8uhW+ zELX8g5P-rdkVvD$?vDgnjHMJEofd9Olff)x62VYkBXf=wJ+=;~6SfOZC9#%f&IcB; z8iqXTj~SDbIi<})V&r&EwOFgP$jcnwHVZ8-6)+>mqgo~nO-os^yF*ACqfE$+TNz}d svVX=(kHZU9&}KZmD|(<|1oj9c&szxDs=vSZ1x@l2hYW`WQwM7GKgXmj0{{R3 diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ja/LC_MESSAGES/ja.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/ja/LC_MESSAGES/ja.mo deleted file mode 100644 index ac33b2ebce6c58e9e69f8ca1fa49d2481905c5c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2191 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 E0i+Eo!~g&Q diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/oc/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/oc/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 6aaba6e4906670f70e49d17cbfee5176ee0dcac2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmZvcO^6&t6vrzjeq_}cv&Qd_!Vff&p3Lm#u#CvE*{pFOyUy;8(W7s=YiCM(sybEG zJMMxI@Z!OX2ZiWGyf{IEu%bdPB7G1<@Su28AvX`66!hr-_4IxOx0#+_ch`IMUj1La z`t8`E_XVzpa6gRuZ`@De{^0=raJ_bu5T`)`4}l+mw}2mkH-n#m6W|EE6Z`_a8~hf0 z0Q?D@1pfr@01q4-&vOKP67Q2B`_F)nf%72y#o!U}Es*`*1v$UV;3MEy;BDZ~Alv^6 za@>DF2_8nWcY!Ctd%-4nAGi!2#M(62!utS=xE1`m;x`q)1KIyakn{f?(f>U4{WF6lIp8($j?*YFA z9|gY$S(iUR&gWlHg2y2SmkjBNl?~>{6e%@wzu0CQqQmJAHMH+4*;h`94#bi+ zQ*LY+lYt|TVp?ldO>}IpmqH8(GEgQLosDel$})Kf9QSLrns}v8WqCcvzCi{1I<$*g zNpt}MA(^I}SW%gEAzJi3okVByo{u^fpW81*E6|LMqO(w>DW~dFji}Lxrs}eBx>=uo zw%(}MC(e@(QOA+-DPc1-<#LXaAZUB;T=C8-#!WA$o{Bn(2AFsIy(w)xvDjK%*iEHT zt4~xLDB_hhODRufDQWXuSy->a^DlQ^h-P-}IP#iu(SnI>0>zthrmMrmtI;`SSV&H( zZB?R!oW}g(f=!E2*p%za1xj==as(*@dLwgspdFM%J!NXKBT~gfp4&uT%r&-6Mj5+Y zzx4U6I1iJ=dNF76G{qiU@G-4{9n?&XpG&*yyG*ZNx?FB_9it1lPkMRy|J+`*xT|!$ z&rmfl`U_oz8e_qn>W#^H(V?_YaF^-R+W}i~v1Le{#a2zJ_>^3kPPIbpeM88FGFObU zafij+VGC$3N(f(iTvZZFcF@Hcf~n)O&7g&sBvX>;GKZL0<9Mn+a diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pl/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pl/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index b75dfb5cac1c636ab46bc6f0c0b0415148256ab9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1471 zcmZ{j&x<2P6vs;)f5l(BE3OLuc%m)|(y^0WaLr6s-Er3)oEgI;yCZs#N_S1ClJ2Ue zx_a6)D~PZNUd6*Ic=09*ir`5PV&*Rp1TX##9zBWQ>h$c42a8lbU9aAI^?hBh|2(zw z8N)b*`2^-Sm``G^-G)Dm@4yxCd+-79NAM)L03Qc`2OkFi0`CV`ZeRMJ1RGeN2A>9> z0iFMA;Dg}1p!1)C_kcyc{~`Dg)}Mo?!LPwb!C$}+aK<0tQ&{gplsk97<|m-De+fPU z{tP|`{s!I&{tY_a|A3EyCt!4XTA-_a9dz|w1D);=d=}K8)AK2KFZdPc@_Y+IPBmPd zv$^4Fy03a#*6DJ)0om1XwYofzQH{H5-cj>7?#9BMeFD>I!jX(!)ONzwW5EqgWM;LQ zViuIG2jf4SE^ z`-0!`{l+HGtT!@TWiiK_@6kYNYv@g#$LqweSw}UwnrA%@M0QssaC7Ep9$N)I=bwgKk{>8_Jr{+sX&K# zqdhu5mbUS>_l8iy)GDoO3L$8oe z*nYm_U+8z~%$e$Ot$)rvHl5jD>-cp2dS!P$ehV=j#B^J$4Yo1Uijy|Hq>>lhSbgxt z;$zAJ+|rD*-FZ;XE6cJ!<>DrL=l}e&GAOmub-Tm$R+`}q-K-0a%@93NC*RR!B5!>j zQc^RPK{@6mVu4Pwzy46PmIB!}E_87-h167+^I*!^=F+uPdE*pPX<}*HZz3!sRe0ogPzowCfkN^Mx diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pt_BR/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/pt_BR/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 82ec9356fb1eeea8c4182fe2906d24138f7aa67a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2201 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 Ve+}o!bR{04zUf0cg8wlNe*+I5N^SrE diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/sk/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/sk/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index c1f23ffbc2549ae466e83faa5fd79c8a8bf0d3e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1822 zcmZvcO>7%Q6vwAfzFa=bm#CVZg4^33>Quy@qg=-v=yVB{ds5J$N# ze=RUx!F(O_F6Lp(&-USl@dvmc{1bc}{0n>r{0DpiJn)DRuYrfb7r|5D)8GQgepkRF z;5D!YegVD#Zh-7}3w##*31q*YLC*gh_$0XR(WzYxZ2vdNx(^{Z>u!Urrw<+l zS3s_BWB2(6$o2dPJ`dgn-voaFIi7d|wE*8EIxEI`C*39uaCi|lu)p!c`1DKFg z4TPx%_Zp=?Ft~pQF<-)DEl4fIIh)5~PMT09VlGkAQLKG#-8!ChHn7q~G-pk&On%?W zt__9kp&~J7Gp!=ZEmn5D#D~*3)YB6s=0j`5q8%&Jxk}kEj}?%ST*;LquM!pJ8b+7Y zr#T@T6kICO0ru<)g|T!pgrO&GDz|}jqU+RHtFr~s^=MHT*XwohNi6efg+o73hh0VW!F&{4Mv2JPrrNT~tjmK% zKh#lht{D2DZ?W863YJkd8wKy9rZ%-2&3A%kBWRwa)=axGbE45|G-@A7p9g&>jZY+A zXPYisuV`7vlFqE+XY*9E`Q9*?Jqvp?EaXrHeI--mx%b>AKf2yqs4dPfp5If~ ztT$@AUq!&hwyWm7l_gS}+3Ib1m3KbwUkFa`*|C@v<%07jv=MsTrqctR*RBK~D5Km| zW!I`m=hUjV>P_rSAA@t!t4!u`o9eZ0QaG6e7pzNtn@mAa1lCYD;qXZHg4s&~^x=%CT2%&8S$U-kdH-)s}!yE5E)wh>DM9gUT^ z>WZCBy>nAsUQgvj8jUxPFTecWX$2cEWAb6_%1tv`ug(PT$h|chPyNbG(Hq&Uyyfgz zn(`Zp@ag>Lcv)?4jjZ3fd0+7Pku_3uEse`NI46qr`@)pBVU^j$?re<;GLj~8dqbnW zBbwNWk!c|=NuQ{wSS@dd@}4P2+TKt(!DM8|G^W@(V^f0KXjF(j1*Y7Lx3^?e(6RB< zI*h9$7lm=T8BOFvaeL+Mk+Z2O?~qeFTRIg>kcyOg3ei zxg0B_rMPMbPEOEfDl$8PFsyRHn(ph_EzvJ%P((P1e3bF`keMQ9J8KGbe<9H$gHw+q cnQ}I?zAB{LM8~z_Bf9;SMVId7dbkJw0-s<8*Z=?k diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/tr/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/tr/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 1e04ff26388f4bd5cd2ab61537d9226aea3605b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2050 zcmai!O>7%Q7=|ZMC^b-^Ex)DWgMyS&t#Lvs1*aiRLYqbpahSAx4?(N@4$z^AHfp%6ZklI2Yd?L1)m3h1y6#1 zfscVB4-VoS2VcebB*^}g;7i~<$bKPs9Q+Jqzb`?q?_2N;xD7r6{syxB?;z*>2PE(q zihTln9ef6?g3p3Czy^BLU=`!LXoBM(MN{0@DLjsXr@^PevmnQP3*>m$K+bm)JOSpz z?_Yqd$2Z_B;13|{u?voYzksaq2!iwXGvG1sJjmZKfGqh95I<4F<1Ba+Wc@w|Iqz4) z@y{S(ybH2!e}e4KHE`YBE7#2$J&7CX`|HQO^2IsfA|O}4FW}(fzPPqixH%`U1D3C^ zBiF*$3%GgRp5wvrdUXF~NbXb2Iz?TZQR=S9^S4lP_ z=B#gtd1*owi}_edH+Zt~%<#3PGjClNqkZ3bYrHc4o-aci#777fiFuo96>;)|jNretmz`SEs?*OvqlY%<1~WF#hJluyUXzd{v5^uhD&aaJ+c6}avz>cG4ktS;=#`~1 zgpAJS2CbniQB&S))67Jz1vg{8Ue%%GvI)P?rd?6z@;e&ZHx#v$Q=$&B$fn8-3`1$) z$g>D*jVg<}Z8l?w0YMUFa#8Q516P(QgTP^{TrP_bTe82r8Rx!F1^WrK3l^i`0|%du6TC})z0^#kj?1A<-iC*1=CY}Rx{^ti>bYy{tVI`% z>Ke7GvP*d*H$D%%D;wnx?W^QnX=!ok@?r5~iN72CZHY*nX?rcB3)Y7@3OYqu#D#79; z&=}(xaTOa_Lkf*!DSEe4FJtVHM6bsRb1A;#VDiYo0d6y5K^2>c-rG2s5zCypce~g` zUgQ~!oBuU4(O{-4sg0c|V`-w^)H$tHIlIuw>9uSL3Kqv4dX7%e@Ua z)~s=|t*NOUA{XCho{CMZV%tk<7Td1aF}~PA;VOg*Z5+^c|0K(9Z!3d;aSH;(DpAAC zG`eqdj_2UCAA13In%X+OKMUq0||41VK1-^Dc$N&HU diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/uk/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/uk/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 5941d4ff80509dfac322c0617ec5e652b468e236..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4393 zcma);TWlOx8OIM$2si=SQYhE-6liLb?6S5KHMQg1onlg_R^k>a#KU;^*q&y0W;-+M zOBI0=w`rqBiGb9RqLe^EAf9lXICkvV5j?>YGZNwj)INdw0zy0?@c_T?%&fh(8`PC| z|8s8N<^TP^Gk*KQ``%D|cJTco-%}q@suTRn2l?UiyALUK0Q^0;6Wn~CQv9j?{5%YH zgC7CE3w{_Zflc5G;K#ul_y9Nwehz#Cd=UIK_$lzW;77qff%k*&fS&;W32p)Z3-YJ7 zVEl3L0Z{xs34Rvb4}KMV9u&Xd1I6z-@DcDbxDA{G#sAx&*#9>u_BUZn@_q>X64(kp z3O)l$TrYwj178Ba489DConL~I$8SK%?~kAc{|0^%+_Wi;^I`BajJJY9=`K)s+YMfY z>pt*R#(&3|57uxdas3sPI{XV1KY5Z9ehz?=_i<42I|)kuuY*s3)8H=f-3+&GPS5p& zdzm+22l#XF3*bB8L*ReF?|}E?T>O~(`T*-6$$?U-PxBQ%MT;DB!f{DGqDnMZvg^hMh>4O%&>Jzm{!uBVBR>Q;f>v>Of%Z zN?6MtMjbB_8zsXjqn&bD7t3ySz;}X@b|X^>_o;(^G^`Hc#Ax3ukL#-Ic_v$B-Yc52 zI#f1Jkp7C1ec9u%8%BOG&Zutlkncsr+Ax#t!7nCEsbR$pwW(Aij{8*?kHonWoI31= z&On*{-JYNhhy5Tb)}oM!$OJ26^^G(JeZqaosGg$lsiVeJbx6j=2&*Y`&Y&E!Y3S^P zdfKhH*z0x1bkU|i=!zrk=;q#oEvnZaF_t8WEP|fMujl2OM^MS?H+qn>txz#nb&oGp$HBY?0fQ8UXo&I&p%vrR7*~bn z{_$#RL5dh6!QyZ}pI6WJsBcL#$)vb%EKK0PKq+!PrQCDWjEp;U({WQpf4Sap$Svg# z)`r4dzt42vGr8l`M>gdS!+wWuE3~!e3Qy+R3c9enqp)jxp}kOOdYYcj^#_g@mK{2# zLqBguhK;BD{HlLa?-_H-(Gz3&&;%oH(d-|pIBq##^ecNg=nd7JA(QJjP6dbcafhy* zZ0hal?Ou(sHD74T+Ak+rci4JH{YP@USNBOsgC@vzdquxQQ9JbR z0XJ&uE7t<2oIBzNm9Rs5RXYs3c6RFYvCHe~YSsI6yJq#V)`E<-ZL^PsN4r{OsgN!0 z?P{wp?djSnkIizTu&1@4Pn}ASu&2<%nO4rUbvAuF_muIZ(!x}qZ%W*8?fLe6YmfX7i_-x~udvAmR>+PIS6feIo;}F293Am%~aCbY+7nR6> zX&4h@nLzHvw=FNV5rt*We}*)s(kY5$3$_5m2##s0z~qFu)X8blox~s-z`#;+QS8ky zxCuFDlJla>4M(ZodmsG?Vb57!C)VMc zEg_BD4WbayP&4U(wUiV128SX;(d@0&)UM)pf%Eg?9V_QE54H^Tz{%K3RyW62;~%sT zxs^E$km@B>-ny>PSelmZBNRIewfMW@IT|){_!oEa0 zCpXEenF(~g`s59%6GEEQ&Fe$9tgbzd=o>06dLf#u@l&d-r&|(K zD*8o)EVqFuT>8}NXpxlUj!lDpAJlL=5~op zP~Jy3MI83FCfw{@sN%Qk?Ap7QP24ncU!76$FGQtv$xPQ}D+<5E^evbZwJeLQ*S$6J z5>KjAdryiz2_b!<*;hfmbBJiQZ_dj(URES0H(?scO5`wNUu+au{!5F`k~!i)guE8x W+sSDa|0?ZS*#2&1R~ diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/zh_CN/LC_MESSAGES/clipboard-indicator.mo b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/locale/zh_CN/LC_MESSAGES/clipboard-indicator.mo deleted file mode 100644 index 3ac63442184c511c9ec092b4d846adee825fc659..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2011 zcmZvaTWl0n7{?Ea7gj|DFL>pcs6ouEyG0=r#Rvc2&Xm@~lR5L7bH2;@ zzW3S z(z$DDUc{XNUj}zzt$=j?L6Gt_gWEt2 zd>m{G?B_r{YzVLC!7*?PxB`;4KY)}+2K#>o>wiG<-*O*gFMzv1Y_YdN%6|l;I#K}( zAmtef){`LRUjgaL=uRk(dL=zbqen0)Ct9w>0<{=~FvwNwi}uzA^+&ZohDqAeJ>dFk zI?`Rzcp8)LjcQvP53GFzr2m1vZVBFD=DD2@KH62o;f~3ZA|o8Z)l7zK89moxs#cQg zj>y{k*nZPVvqsg>M20nHglhS3a^4qwrghsftq!c#VjE4v5r(s2C-6ajq!3BgXy$a0 zq{Hu=$lmhv@MislV23o*U`=M5s1-tvPFestuC_YD;x=m5934)F#U~EOX{g|EKHCDD z*~+!FYN;9=ZLS-&uojdaw?vyR+G{89UF$xt_!cv72Z`dA-ljs5teF(-sK`^g(X-5VsSGkEZhvJ#MrDl|a zrj@m0+{o3I_TK0o?tku$>{$&=H4B4uBp>FDmt}dl zGI>&Vk5z|CZco7-?U6m-RAy)0i!1KMac`t7`v(8Gb&1K&sp_dICW`~^TsL#)JK-O| z537`CipT&`2s>1Hr%nI`}ML{TJ(lb z%jrSy+9VQHyNawjak_G)yV}1Z7bg+&`C7eA@ye6K8i>wa0PepUFr@EMccU2gA0r8p{k` { - const originalValue = this.schema.get_strv(pref)[0]; - - if (!originalValue) { - button.set_label(_('Disabled')); - } - else { - button.set_label(originalValue); - } - }; - - const startEditing = () => { - button.isEditing = button.label; - button.set_label(_('Enter shortcut')); - }; - - const revertEditing = () => { - button.set_label(button.isEditing); - button.isEditing = null; - }; - - const stopEditing = () => { - setLabelFromSettings(); - button.isEditing = null; - }; - - setLabelFromSettings(); - - button.connect('clicked', () => { - if (button.isEditing) { - revertEditing(); - return; - } - - startEditing(); - - const eventController = new Gtk.EventControllerKey(); - button.add_controller(eventController); - - let debounceTimeoutId = null; - const connectId = eventController.connect('key-pressed', (_ec, keyval, keycode, mask) => { - if (debounceTimeoutId) clearTimeout(debounceTimeoutId); - - mask = mask & Gtk.accelerator_get_default_mod_mask(); - - if (mask === 0) { - switch (keyval) { - case Gdk.KEY_Escape: - revertEditing(); - return Gdk.EVENT_STOP; - case Gdk.KEY_BackSpace: - this.schema.set_strv(pref, []); - setLabelFromSettings(); - stopEditing(); - eventController.disconnect(connectId); - return Gdk.EVENT_STOP; - } - } - - const selectedShortcut = Gtk.accelerator_name_with_keycode( - null, - keyval, - keycode, - mask - ); - - debounceTimeoutId = setTimeout(() => { - eventController.disconnect(connectId); - this.schema.set_strv(pref, [selectedShortcut]); - stopEditing(); - }, 400); - - return Gdk.EVENT_STOP; - }); - - button.show(); - }); - - return button; - } -} diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/registry.js b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/registry.js deleted file mode 100644 index b3b253d..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/registry.js +++ /dev/null @@ -1,281 +0,0 @@ -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; -import St from 'gi://St'; -import { PrefsFields } from './constants.js'; - -const FileQueryInfoFlags = Gio.FileQueryInfoFlags; -const FileCopyFlags = Gio.FileCopyFlags; -const FileTest = GLib.FileTest; - -export class Registry { - constructor ({ settings, uuid }) { - this.uuid = uuid; - this.settings = settings; - this.REGISTRY_FILE = 'registry.txt'; - this.REGISTRY_DIR = GLib.get_user_cache_dir() + '/' + this.uuid; - this.REGISTRY_PATH = this.REGISTRY_DIR + '/' + this.REGISTRY_FILE; - this.BACKUP_REGISTRY_PATH = this.REGISTRY_PATH + '~'; - } - - write (entries) { - const registryContent = []; - - for (let entry of entries) { - const item = { - favorite: entry.isFavorite(), - mimetype: entry.mimetype() - }; - - registryContent.push(item); - - if (entry.isText()) { - item.contents = entry.getStringValue(); - } - else if (entry.isImage()) { - const filename = this.getEntryFilename(entry); - item.contents = filename; - this.writeEntryFile(entry); - } - } - - this.writeToFile(registryContent); - } - - writeToFile (registry) { - let json = JSON.stringify(registry); - let contents = new GLib.Bytes(json); - - // Make sure dir exists - GLib.mkdir_with_parents(this.REGISTRY_DIR, parseInt('0775', 8)); - - // Write contents to file asynchronously - let file = Gio.file_new_for_path(this.REGISTRY_PATH); - file.replace_async(null, false, Gio.FileCreateFlags.NONE, - GLib.PRIORITY_DEFAULT, null, (obj, res) => { - - let stream = obj.replace_finish(res); - - stream.write_bytes_async(contents, GLib.PRIORITY_DEFAULT, - null, (w_obj, w_res) => { - - w_obj.write_bytes_finish(w_res); - stream.close(null); - }); - }); - } - - async read () { - return new Promise(resolve => { - if (GLib.file_test(this.REGISTRY_PATH, FileTest.EXISTS)) { - let file = Gio.file_new_for_path(this.REGISTRY_PATH); - let CACHE_FILE_SIZE = this.settings.get_int(PrefsFields.CACHE_FILE_SIZE); - - file.query_info_async('*', FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, null, (src, res) => { - // Check if file size is larger than CACHE_FILE_SIZE - // If so, make a backup of file, and resolve with empty array - let file_info = src.query_info_finish(res); - - if (file_info.get_size() >= CACHE_FILE_SIZE * 1024 * 1024) { - let destination = Gio.file_new_for_path(this.BACKUP_REGISTRY_PATH); - - file.move(destination, FileCopyFlags.OVERWRITE, null, null); - resolve([]); - return; - } - - file.load_contents_async(null, (obj, res) => { - let [success, contents] = obj.load_contents_finish(res); - - if (success) { - let max_size = this.settings.get_int(PrefsFields.HISTORY_SIZE); - const registry = JSON.parse(new TextDecoder().decode(contents)); - const entriesPromises = registry.map( - jsonEntry => { - return ClipboardEntry.fromJSON(jsonEntry) - } - ); - - Promise.all(entriesPromises).then(clipboardEntries => { - clipboardEntries = clipboardEntries - .filter(entry => entry !== null); - - let registryNoFavorite = clipboardEntries - .filter(entry => entry.isFavorite()); - - while (registryNoFavorite.length > max_size) { - let oldestNoFavorite = registryNoFavorite.shift(); - let itemIdx = clipboardEntries.indexOf(oldestNoFavorite); - clipboardEntries.splice(itemIdx,1); - - registryNoFavorite = clipboardEntries.filter( - entry => entry.isFavorite() - ); - } - - resolve(clipboardEntries); - }).catch(e => { - console.error(e); - }); - } - else { - console.error('Clipboard Indicator: failed to open registry file'); - } - }); - }); - } - else { - resolve([]); - } - }); - } - - #entryFileExists (entry) { - const filename = this.getEntryFilename(entry); - return GLib.file_test(filename, FileTest.EXISTS); - } - - async getEntryAsImage (entry) { - const filename = this.getEntryFilename(entry); - - if (entry.isImage() === false) return; - - if (this.#entryFileExists(entry) == false) { - await this.writeEntryFile(entry); - } - - const gicon = Gio.icon_new_for_string(this.getEntryFilename(entry)); - const stIcon = new St.Icon({ gicon }); - return stIcon; - } - - getEntryFilename (entry) { - return `${this.REGISTRY_DIR}/${entry.asBytes().hash()}`; - } - - async writeEntryFile (entry) { - if (this.#entryFileExists(entry)) return; - - let file = Gio.file_new_for_path(this.getEntryFilename(entry)); - - return new Promise(resolve => { - file.replace_async(null, false, Gio.FileCreateFlags.NONE, - GLib.PRIORITY_DEFAULT, null, (obj, res) => { - - let stream = obj.replace_finish(res); - - stream.write_bytes_async(entry.asBytes(), GLib.PRIORITY_DEFAULT, - null, (w_obj, w_res) => { - - w_obj.write_bytes_finish(w_res); - stream.close(null); - resolve(); - }); - }); - }); - } - - async deleteEntryFile (entry) { - const file = Gio.file_new_for_path(this.getEntryFilename(entry)); - - try { - await file.delete_async(GLib.PRIORITY_DEFAULT, null); - } - catch (e) { - console.error(e); - } - } -} - -export class ClipboardEntry { - #mimetype; - #bytes; - #favorite; - - static #decode (contents) { - return Uint8Array.from(contents.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); - } - - static async fromJSON (jsonEntry) { - const mimetype = jsonEntry.mimetype || 'text/plain;charset=utf-8'; - const favorite = jsonEntry.favorite; - let bytes; - - if (mimetype.startsWith('text/')) { - bytes = new TextEncoder().encode(jsonEntry.contents); - } - else { - const filename = jsonEntry.contents; - if (!GLib.file_test(filename, FileTest.EXISTS)) return null; - - let file = Gio.file_new_for_path(filename); - - bytes = await new Promise((resolve, reject) => file.load_contents_async(null, (obj, res) => { - let [success, contents] = obj.load_contents_finish(res); - - if (success) { - resolve(contents); - } - else { - reject( - new Error('Clipboard Indicator: could not read image file from cache') - ); - } - })); - } - - return new ClipboardEntry(mimetype, bytes, favorite); - } - - constructor (mimetype, bytes, favorite) { - this.#mimetype = mimetype; - this.#bytes = bytes; - this.#favorite = favorite; - } - - #encode () { - if (this.isText()) { - return this.getStringValue(); - } - - return [...this.#bytes] - .map(x => x.toString(16).padStart(2, '0')) - .join(''); - } - - getStringValue () { - if (this.isImage()) { - return `[Image ${this.asBytes().hash()}]`; - } - return new TextDecoder().decode(this.#bytes); - } - - mimetype () { - return this.#mimetype; - } - - isFavorite () { - return this.#favorite; - } - - set favorite (val) { - this.#favorite = !!val; - } - - isText () { - return this.#mimetype.startsWith('text/'); - } - - isImage () { - return this.#mimetype.startsWith('image/'); - } - - asBytes () { - return GLib.Bytes.new(this.#bytes); - } - - equals (otherEntry) { - return this.getStringValue() === otherEntry.getStringValue(); - // this.asBytes().equal(otherEntry.asBytes()); - } -} diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/gschemas.compiled deleted file mode 100644 index dc18b7990db05ea9b2a61e45b5dd9ed5231d1942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1612 zcmZuxO^6gn7_C)zjjp=uu9`i0kwEXEW>y7>B6?U*!8rtkAfgG?)3r0j_Ea_9HM5zB zihA%jFV$B zrz$tfdQpuT@bOYds|F@`bgK|=G0IpY}zhBX(X8lR<4nRGK z-_WO~KL?%%?sq*-0?1LhhWXSy zhsWUGfX^;9F43pn2LB)MOJH!XsfB2W*WkvO5KYx=Ygw2tHGR$@1g|LXWcZ6r)Q^mr zot@QI#i^Eyx*zj0+g1@$qIlN3ELOS9a@{j}DO6jJ*q~0rS}S#i)5P{FkNN-2GuG-v zIxA!6z3Z?F2Igy<0v}R;XxZVr7|gdE(%!E-F-2H-;+CvbdG3}FA7PzL6<*7@i|Uro zV3dAtdJ2(_OAszMTZYB{d1rm@(gTM+#yyKvF*ue)r`qG2uku12%$%jFAL>*-iRNtrp&YN89djd~bCQVKQ00n&Ic?s^@E& z^6fgBWj!>@dT5sQm1bH0pJrJXqUgAume^uPVpGNY4vu{;YMsdf2jBGNMH$*K&j|;@ up2;xU;Y3*4zSnqoxKCkHbbBQ diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/org.gnome.shell.extensions.clipboard-indicator.gschema.xml b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/org.gnome.shell.extensions.clipboard-indicator.gschema.xml deleted file mode 100644 index b892590..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/schemas/org.gnome.shell.extensions.clipboard-indicator.gschema.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - true - Add button to paste an entry - - If true, adds another button to each menu entry that lets you immediately paste it - - - - - false - Display the pinned section on the bottom - - If true, places the "pinned" section on the bottom - - - - - true - Enable the deletion of clipboard items from your history - - If true, displays 'delete' buttons on each item, and a 'Clear History' option - - - - - 15 - The number of items to save in history - - - - - - 0 - What to display in top bar - - - - - true - Remove down arrow in top bar - - - - 30 - Amount of visible characters for clipboard items - - The number of characters to display for every clipboard item in - the history menu - - - - - - 10 - Amount of visible characters in topbar - - The number of characters to display for current clipboard item in the topbar - - - - - - 5 - The allowed size for the registry cache file in MB - - If the cache overflows this limit, the file will be overriden. - High limit might cause slowness of shell startup. - - - - - - false - Disable the registry cache file for favorites and use memory only - - Contents which are not favorites are not stored and retrieved from a cache (registry.txt) file. - This can avoid writing passwords to a plaintext file, but at the cost of persistant history. - Your clipboard history, except favorite items, is lost after a gnome-shell session ends or the extension is reloaded. - - - - - false - Show notification on copy to clipboard - - If true, a notification is shown when content is copied to clipboard. - - - - - true - Show confirmation dialog on Clear History - - If true, a confirmation dialog is shown when attempting to Clear History. - - - - - false - Remove whitespace around text - - If true, white spaces around text will be removed. - - - - false - Move items to the top of the list when selected. - - If true, move items to the top of the list when it is selected. - - - - false - Keep selected item on clear - - Whether to keep the currently selected entry in the clipboard - after clearing the history - - - - true - Enable the keyboard shortcuts - - If true, user can delete and cycle through the history with keyboard shortcuts - - - - F10']]]> - Key to clear the history - - - - - F11']]]> - Key to cycle to the previous entry in the clipboard - - - - - F12']]]> - Next entry - - Key to cycle to the next entry in the clipboard - - - - F9']]]> - Toggle the menu - - Key to toggle the clipboard menu - - - - F8']]]> - Toggle "Private Mode" - - Key to toggle the private mode - - - - diff --git a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/stylesheet.css b/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/stylesheet.css deleted file mode 100644 index ba50e90..0000000 --- a/.local/share/gnome-shell/extensions/clipboard-indicator@tudmotu.com/stylesheet.css +++ /dev/null @@ -1,71 +0,0 @@ -.clipboard-indicator-hbox.private-mode { - color: rgba(255,255,255,0.3); -} - -.ci-notification-label { - font-weight: bold; - color: #ffffff; - background-color: rgba(10,10,10,0.7); - border-radius: 6px; - font-size:2em; - padding:.5em; - width:400px; -} - -.popup-menu-item .ci-action-btn StIcon { - icon-size:1.2em; - margin-left:.25em; -} - -.popup-menu-item StEntry StIcon { - icon-size:1em; - margin:0 .25em; -} - -.clipboard-indicator-empty-state { - width:350px; - color:#aaa; -} - -.clipboard-indicator-empty-state StIcon { - icon-size:5em; - margin-top:3em; -} - -.clipboard-indicator-empty-state StLabel { - margin:1em 0 3em 0; -} - -.ci-history-menu-section { - max-height:450px; -} - -.ci-main-menu-section StButton.ci-pin-btn { - color: rgba(255,255,255,0.3); -} - -.clipboard-hidden { - display:none!important; -} - -.clipboard-menu-icon { - width:1em; - height:1em; - margin-right:.5em; -} - -.clipboard-menu-img-preview { - border:solid 1px white; - overflow:hidden; - width:1.5em; - height:1.5em; - margin:0; - padding:0; -} - -.clipboard-indicator-img-preview { - border:solid 1px white; - width:1em; - height:1em; - margin-right:.25em; -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/color.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/color.js deleted file mode 100644 index b6e5dc5..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/color.js +++ /dev/null @@ -1,187 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import { Format } from './const.js'; -import { array, vmap, luminance } from './util.js'; - -const percent = x => `${Math.round(x * 100)}%`; // 0.111 => '11%' -const genStops = n => array(n, i => i / n).concat(1); // `n` is the steps -const parseHEX = m => Math.clamp(parseInt(m, 16), 0, 255); -const zip = (ks, vs) => Object.fromEntries(ks.map((k, i) => [k, vs[i]])); -const parseHSL = (m, i) => i ? Math.clamp(parseInt(m) / 100, 0, 1) : Math.clamp(parseInt(m), 0, 360); - -// Ref: https://en.wikipedia.org/wiki/HSL_and_HSV -function rgb2hsv(rgb) { - let { r, g, b } = vmap(rgb, x => x / 255), - mx = Math.max(r, g, b), - mn = Math.min(r, g, b), - d = mx - mn, - s = mx === 0 ? 0 : d / mx, - k = 0; - if(d !== 0) { // chromatic - switch(mx) { - case r: k = (g - b) / d + (g < b ? 6 : 0); break; - case g: k = (b - r) / d + 2; break; - case b: k = (r - g) / d + 4; break; - } - } - return { h: k * 60, s, v: mx }; -} - -function hsv2rgb({ h, s, v }) { - h = h / 60 % 6; - let k = Math.floor(h), - f = h - k, - p = v * (1 - s), - q = v * (1 - f * s), - t = v * (1 - (1 - f) * s), - r = [v, q, p, p, t, v][k] * 255, - g = [t, v, v, q, p, p][k] * 255, - b = [p, p, t, v, v, q][k] * 255; - return { r, g, b }; -} - -function hsl2hsv({ h, s, l }) { - let v = l + s * Math.min(l, 1 - l); - return { h, s: v === 0 ? 0 : 2 * (1 - l / v), v }; -} - -function hsv2hsl({ h, s, v }) { - let l = v * (1 - s / 2); - return { h, s: l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l), l }; -} - -// Ref: http://www.easyrgb.com/en/math.php -function cmyk2rgb({ c, m, y, k }) { - return vmap({ r: c, g: m, b: y }, x => (1 - x * (1 - k) - k) * 255); -} - -function rgb2cmyk({ r, g, b }) { - let cmy = [r, g, b].map(x => 1 - x / 255), - n = Math.min(...cmy.values()), - [c, m, y, k] = n === 1 ? [0, 0, 0, 1] : cmy.map(x => (x - n) / (1 - n)).concat(n); - return { c, m, y, k }; -} - -export class Color { - #rgb; - - constructor(raw = 0, rgb) { // raw <- uint - if(rgb) { - this.#rgb = { ...rgb }; - this.format = raw; - } else { - let [r, g, b, format] = [24, 16, 8, 0].map(x => raw >>> x & 0xff); - this.#rgb = { r, g, b }; - this.format = format; - } - } - - set rgb(rgb) { - this.#rgb = vmap(rgb, Math.round); - } - - get rgb() { - return { ...this.#rgb }; - } - - set hsv(hsv) { - this.rgb = hsv2rgb(hsv); - } - - get hsv() { - return rgb2hsv(this.#rgb); - } - - set hsl(hsl) { - this.hsv = hsl2hsv(hsl); - } - - get hsl() { - return hsv2hsl(this.hsv); - } - - get cmyk() { - return rgb2cmyk(this.#rgb); - } - - set cmyk(cmyk) { - this.rgb = cmyk2rgb(cmyk); - } - - equal(color) { - return this.toRaw() === color; - } - - copy() { - return new Color(this.format, this.#rgb); - } - - update(type, value) { - switch(type) { - case 'r': case 'g': case 'b': Object.assign(this.#rgb, { [type]: Math.round(value) }); break; - case 'h': case 's': case 'l': this.hsl = Object.assign(this.hsl, { [type]: value }); break; - } - return this; - } - - fromClutter({ red: r, green: g, blue: b }) { // sync with a Clutter.Color - this.#rgb = { r, g, b }; - } - - fromString(str) { - return [ - [/^ *#([0-9a-f]{2})([0-9a-f]{2})([0-91-f]{2}) *$/i, parseHEX, 'rgb'], - [/^ *rgb\( *(\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3}) *\) *$/, m => Math.clamp(parseInt(m), 0, 255), 'rgb'], - [/^ *hsl\( *(\d{1,3}) *, *(\d{1,3})% *, *(\d{1,3})% *\) *$/, parseHSL, 'hsl'], - [/^ *([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2}) *$/i, parseHEX, 'rgb'], - [/^ *hsv\( *(\d{1,3}) *, *(\d{1,3})% *, *(\d{1,3})% *\) *$/, parseHSL, 'hsv'], - [/^ *cmyk\( *(\d{1,3})% *, *(\d{1,3})% *, *(\d{1,3})% *, *(\d{1,3})% *\) *$/, m => Math.clamp(parseInt(m) / 100, 0, 1), 'cmyk'], - ].some(([r, f, t], i) => { - let [, ...ms] = str.match(r) ?? []; - if(!ms.length) return false; - this[t] = zip([...t], ms.map(f)); - this.format = i; // sort by Format - return true; - }); - } - - toRaw() { - let { r, g, b } = this.#rgb; - return [r, g, b, this.format].reduce((a, x) => a << 8 | x) >>> 0; - } - - toRGBHSL() { - return Object.assign(this.hsl, this.#rgb); - } - - toText(format) { - switch(format ?? this.format) { - case Format.RGB: return (({ r, g, b }) => `rgb(${r}, ${g}, ${b})`)(this.#rgb); - case Format.HSL: return (({ h, s, l }) => `hsl(${Math.round(h)}, ${percent(s)}, ${percent(l)})`)(this.hsl); - case Format.HSV: return (({ h, s, v }) => `hsv(${Math.round(h)}, ${percent(s)}, ${percent(v)})`)(this.hsv); - case Format.CMYK: return (({ c, m, y, k }) => `cmyk(${c}, ${m}, ${y}, ${k})`)(vmap(this.cmyk, percent)); - case Format.hex: return (this.toRaw() >>> 8).toString(16).padStart(6, '0'); - default: return `#${(this.toRaw() >>> 8).toString(16).padStart(6, '0')}`; - } - } - - toMarkup(format) { // FIXME: workaround for https://gitlab.gnome.org/GNOME/mutter/-/issues/1324 - return ` ${this.toText(format)}`; - } - - toRGBA(alpha = 1) { - let { r, g, b } = this.#rgb; - return [r / 255, g / 255, b / 255, alpha]; - } - - toStops(type) { // linear gradient color stop - let color = this.copy(); - switch(type) { - case 'r': case 'g': case 'b': return genStops(1).map(x => [x].concat(color.update(type, x * 255).toRGBA())); - case 'h': return genStops(12).map(x => [x].concat(color.update(type, x * 360).toRGBA())); - case 's': return genStops(1).reverse().map(x => [x].concat(color.update(type, x).toRGBA())); // `s` starts from the end - case 'l': return genStops(4).sort((a, b) => Math.abs(a - 0.5) - Math.abs(b - 0.5)).map(x => [x].concat(color.update(type, x).toRGBA())); // `l` starts from the middle - } - } -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/const.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/const.js deleted file mode 100644 index 3725799..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/const.js +++ /dev/null @@ -1,25 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -export const Format = { HEX: 0, RGB: 1, HSL: 2, hex: 3, HSV: 4, CMYK: 5 }; - -export const Field = { - MKEY: 'menu-key', - QKEY: 'quit-key', - COPY: 'auto-copy', - MSIZ: 'menu-size', - MSTL: 'menu-style', - NTFS: 'notify-style', - FMT: 'enable-format', - HIST: 'color-history', - NTF: 'enable-notify', - PVWS: 'preview-style', - FMTS: 'default-format', - PVW: 'enable-preview', - STRY: 'enable-systray', - KEY: 'enable-shortcut', - PRST: 'persistent-mode', - CLCT: 'color-collection', - TICN: 'systray-dropper-icon', - KEYS: 'color-picker-shortcut', -}; diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/extension.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/extension.js deleted file mode 100644 index b7d2563..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/extension.js +++ /dev/null @@ -1,654 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import St from 'gi://St'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Meta from 'gi://Meta'; -import Cairo from 'gi://cairo'; -import Shell from 'gi://Shell'; -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Slider from 'resource:///org/gnome/shell/ui/slider.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; - -import { Color } from './color.js'; -import { Field, Format as Formats } from './const.js'; -import { encode, omap, bmap, xnor, gerror, gprops, raise } from './util.js'; -import { StButton, IconButton, MenuItem, RadioItem, IconItem, TrayIcon } from './menu.js'; -import { Fulu, BaseExtension, Destroyable, manageSource, omit, getSignalHolder, _, getSelf } from './fubar.js'; - -const setCursor = x => x && global.display.set_cursor(Meta.Cursor[x]); -const setClipboard = x => St.Clipboard.get_default().set_text(St.ClipboardType.CLIPBOARD, x); -const genColorSwatch = x => encode(` - -`); - -const Format = bmap(Formats); -const Notify = { MSG: 0, OSD: 1 }; - -class ColorItem extends MenuItem { - static { - GObject.registerClass(this); - } - - constructor(callback, item) { - super('', () => setClipboard(this._color.toText())); - this.label.set_x_expand(true); - this._btn = new IconButton({ style_class: 'color-picker-setting' }, () => callback(this._color.toRaw())); - this.add_child(this._btn); - this.setItem(item); - } - - setItem(item) { - if(!item) return; - let [icon, raw] = item; - this._btn.setIcon(icon ? 'starred-symbolic' : 'non-starred-symbolic'); - if(this._color?.equal(raw)) return; - this._color = new Color(raw); - this.label.clutter_text.set_markup(this._color.toMarkup()); - } -} - -class ColorSection extends PopupMenu.PopupMenuSection { - constructor(list, callback) { - super(); - this.setList(list, callback); - } - - setList(list, callback) { - let items = this._getMenuItems(); - let diff = list.length - items.length; - if(diff > 0) for(let a = 0; a < diff; a++) this.addMenuItem(new ColorItem(callback)); - else if(diff < 0) for(let a = 0; a > diff; a--) items.at(a - 1).destroy(); - this._getMenuItems().forEach((x, i) => x.setItem(list[i])); - } -} - -class ColorSlider extends Slider.Slider { - static { - GObject.registerClass(this); - } - - constructor(type, number, base, color, callback) { - super(number / base); - this.type = type; - this.base = base; - this.color = color; - this.step = base > 1 ? 1 / base : 0.01; - this.connect('notify::value', () => (this._dragging || this.get_parent().active) && callback(this.number)); - } - - get number() { - return this.value * this.base; - } - - set number(number) { - let value = number / this.base; - if(value === this.value) this.queue_repaint(); - else this.value = value; - } - - vfunc_repaint() { // ignore border on colorful bg - let cr = this.get_context(), - themeNode = this.get_theme_node(), - [width, height] = this.get_surface_size(), - gradient = new Cairo.LinearGradient(0, 0, width, 0), - barLevelHeight = themeNode.get_length('-barlevel-height'), - barLevelRadius = Math.min(width, barLevelHeight) / 2; - // draw background - cr.arc(barLevelRadius, height / 2, barLevelRadius, Math.PI * (1 / 2), Math.PI * (3 / 2)); - cr.arc(width - barLevelRadius, height / 2, barLevelRadius, Math.PI * 3 / 2, Math.PI / 2); - this.color.toStops(this.type).forEach(x => gradient.addColorStopRGBA(...x)); - cr.setSource(gradient); - cr.fill(); - - let handleRadius = themeNode.get_length('-slider-handle-radius'), - ceiledHandleRadius = Math.ceil(handleRadius), - handleX = ceiledHandleRadius + (width - 2 * ceiledHandleRadius) * this._value / this._maxValue, - handleY = height / 2; - // draw handle - cr.setSourceRGBA(...this.color.toRGBA()); - cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI); - cr.fill(); - Clutter.cairo_set_source_color(cr, themeNode.get_foreground_color()); - cr.arc(handleX, handleY, barLevelRadius, 0, 2 * Math.PI); - cr.fill(); - - cr.$dispose(); - } - - vfunc_key_press_event(event) { - let key = event.get_key_symbol(); - if(key === Clutter.KEY_Right || key === Clutter.KEY_Left) { - let delta = key === Clutter.KEY_Right ? this.step : -this.step; - this.value = Math.clamp(this._value + delta, 0, this._maxValue); - return Clutter.EVENT_STOP; - } - return super.vfunc_key_press_event(event); - } - - scroll(event) { - if(event.is_pointer_emulated()) return Clutter.EVENT_PROPAGATE; - let delta = (direction => { - switch(direction) { - case Clutter.ScrollDirection.UP: return 1; - case Clutter.ScrollDirection.DOWN: return -1; - case Clutter.ScrollDirection.SMOOTH: return -event.get_scroll_delta().at(1); - default: return 0; - } - })(event.get_scroll_direction()); - this.value = Math.clamp(this._value + delta * this.step, 0, this._maxValue); - return Clutter.EVENT_STOP; - } -} - -class SliderItem extends PopupMenu.PopupBaseMenuItem { - static { - GObject.registerClass(this); - } - - constructor(type, number, base, color, callback) { - super({ activate: false }); - let label = new St.Label({ text: type.toUpperCase(), x_expand: false }); - this._slider = new ColorSlider(type, number, base, color, callback); - this.connect('key-press-event', (_a, event) => this._slider.vfunc_key_press_event(event)); - [label, this._slider].forEach(x => this.add_child(x)); - } - - setNumber(number) { - this._slider.number = number; - } -} - -class ColorMenu extends PopupMenu.PopupMenu { - constructor(area) { - super(area._view, 0.15, St.Side.LEFT); - this.color = area._color; - Main.layoutManager.addTopChrome(this.actor); - this._manager = new PopupMenu.PopupMenuManager(area); - this.actor.add_style_class_name('color-picker-menu'); - this._manager.addMenu(this); - this._addMenuItems(); - this.actor.hide(); - } - - _addMenuItems() { - let { r, g, b, h, s, l } = this.color.toRGBHSL(); - this._menus = { - HEX: this._genHEXItem(), - RGB: new PopupMenu.PopupSeparatorMenuItem(), - r: this._genSliderItem({ r }, 255), - g: this._genSliderItem({ g }, 255), - b: this._genSliderItem({ b }, 255), - HSL: new PopupMenu.PopupSeparatorMenuItem(), - h: this._genSliderItem({ h }, 360), - s: this._genSliderItem({ s }, 1), - l: this._genSliderItem({ l }, 1), - other: new PopupMenu.PopupSeparatorMenuItem(_('Others')), - HSV: new MenuItem('hsv', () => this._emitSelected(Format.HSV)), - CMYK: new MenuItem('cmyk', () => this._emitSelected(Format.CMYK)), - clip: this._genClipItem(), - }; - Object.values(this._menus).forEach(x => this.addMenuItem(x)); - } - - _genSliderItem(initial, base) { - let [[type, value]] = Object.entries(initial); - return new SliderItem(type, value, base, this.color, x => this.updateSlider(type, x)); - } - - updateSlider(type, value) { - this.color.update(type, value); - Object.entries(this.color.toRGBHSL()).forEach(([k, v]) => k === type || this._menus[k].setNumber(v)); - this._updateLabelText(); - } - - _updateLabelText() { - this._menus.HEX.label.clutter_text.set_markup(this.color.toMarkup(Format.HEX)); - ['RGB', 'HSL', 'HSV', 'CMYK'].forEach(x => this._menus[x].label.set_text(this.color.toText(Format[x]))); - } - - _genClipItem() { - let item = new PopupMenu.PopupMenuItem(_('Read from clipboard')); - item.activate = () => St.Clipboard.get_default().get_text(St.ClipboardType.CLIPBOARD, (_c, text) => { - this.open(BoxPointer.PopupAnimation.NONE); - if(this.color.fromString(text ?? '')) this.updateSlider(); - else console.error(`[${getSelf().metadata.name}]`, `Unknown color format: ${text}`); - }); - return item; - } - - _genHEXItem() { - let item = new MenuItem('', () => this._emitSelected(Format.HEX)); - ['RGB', 'HSL', 'hex'].reverse().forEach(x => item.insert_child_at_index(new StButton({ - x_expand: false, label: x, style_class: 'color-picker-button button', - }, () => { this.close(); this._emitSelected(Format[x]); }), 0)); - return item; - } - - summon() { - if(this.isOpen) this.close(); - this.updateSlider(); - this.open(BoxPointer.PopupAnimation.NONE); - } - - _emitSelected(format) { - this.color.format = format; - this.emit('color-selected', this.color); - } -} - -class ColorLabel extends BoxPointer.BoxPointer { - static { - GObject.registerClass(this); - } - - constructor() { - super(St.Side.TOP); - this.visible = false; - this.cursor_type = 'CROSSHAIR'; - this.style_class = 'color-picker-boxpointer'; - Main.layoutManager.addTopChrome(this); - this._label = new St.Label({ style_class: 'color-picker-label' }); - this.bin.set_child(this._label); - let s = Math.round(Meta.prefs_get_cursor_size() * 0.8); - this._cursor = new Clutter.Actor({ opacity: 0, width: s, height: s }); - manageSource(this, () => omit(this, '_cursor')); - Main.uiGroup.add_actor(this._cursor); - } - - setColor(x, y, color) { - this.hide(); // NOTE: workaround for box-shadow afterimage since 45.beta - this._label.clutter_text.set_markup(`\u2001 ${color.toText()}`); - this._cursor.set_position(x, y); - this.setPosition(this._cursor, 0); - this.show(); - } -} - -class RecolorEffect extends Shell.GLSLEffect { - // copy from js/ui/screenshot.js since it's private since 45.beta - static { - GObject.registerClass({ - Properties: gprops({ - threshold: ['float', 0, 1, 0.12], - smoothing: ['float', 0, 1, 0.10], // 0.2 + 0.02 - threshold - color: ['boxed', Clutter.Color.$gtype], - chroma: ['boxed', Clutter.Color.$gtype], - }), // chroma -> color - }, this); - } - - constructor(param) { - super({ chroma: new Clutter.Color({ red: 80, green: 219, blue: 181 }), ...param }); - this.color ??= this.chroma.copy(); - ['color', 'chroma', 'threshold', 'smoothing'].forEach(x => { - let _x = `_${x}`; - let location = this.get_uniform_location(x); - this._updateUniform(x, _x, location); - this.connect(`notify::${x}`, () => this._updateUniform(x, _x, location)); - }); - } - - _updateUniform(key, _key, location) { - if(isNaN(this[key])) { - if(this[_key]?.equal(this[key])) return; - let { red, green, blue } = this[_key] = this[key].copy(); - this.set_uniform_float(location, 3, [red / 255, green / 255, blue / 255]); - } else { - if(this[_key] === this[key]) return; - this.set_uniform_float(location, 1, [this[_key] = this[key]]); - } - this.queue_repaint(); - } - - vfunc_build_pipeline() { - // Conversion parameters from https://en.wikipedia.org/wiki/YCbCr - let dcl = ` - vec3 rgb2yCrCb(vec3 c) { \n - float y = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b; \n - float cr = 0.7133 * (c.r - y); \n - float cb = 0.5643 * (c.b - y); \n - return vec3(y, cr, cb); \n - } \n - uniform vec3 chroma; \n - uniform vec3 color; \n - uniform float threshold; \n - uniform float smoothing; \n`; - let src = ` - vec3 mask = rgb2yCrCb(chroma.rgb); \n - vec3 yCrCb = rgb2yCrCb(cogl_color_out.rgb); \n - float blend = smoothstep(threshold, \n - threshold + smoothing, \n - distance(yCrCb.gb, mask.gb)); \n - cogl_color_out.rgb = \n - mix(color, cogl_color_out.rgb, blend); \n`; - this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, dcl, src, false); - } -} - -class ColorIcon extends St.Icon { - static { - GObject.registerClass(this); - } - - constructor() { - let effect = new RecolorEffect(); // chroma default to the color-pick.svg below - let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri('resource:///org/gnome/shell/icons/scalable/actions/color-pick.svg') }); - super({ visible: false, gicon, effect, icon_size: Meta.prefs_get_cursor_size() * 1.45 }); - Main.layoutManager.addTopChrome(this); - this.cursor_type = 'BLANK'; - this._effect = effect; - } - - setColor(x, y, color) { - this._effect.color = color; - this.set_position(x, y); - this.show(); - } -} - -class ColorArea extends St.Widget { - static { - GObject.registerClass({ - Signals: { - end_pick: { param_types: [GObject.TYPE_BOOLEAN] }, - notify_color: { param_types: [GObject.TYPE_JSOBJECT] }, - }, - }, this); - } - - constructor({ fulu, once, format }) { - super({ reactive: true }); - Main.layoutManager.addTopChrome(this); - Main.pushModal(this, { actionMode: Shell.ActionMode.NORMAL }); - this.add_constraint(new Clutter.BindConstraint({ source: global.stage, coordinate: Clutter.BindCoordinate.ALL })); - - this.once = once ?? false; - this._color = new Color(format); - this._picker = new Shell.Screenshot(); - this._pointer = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.POINTER_DEVICE); - manageSource(this, () => { omit(this, 'preview', '_pointer', '_picker'); }); - this.connect('popup-menu', () => this._menu?.summon()); - this._bindSettings(fulu); - } - - _bindSettings(fulu) { - this._fulu = fulu.attach({ - pvstyle: [Field.PVWS, 'uint'], - menukey: [Field.MKEY, 'string'], - quitkey: [Field.QKEY, 'string'], - persist: [Field.PRST, 'boolean'], - preview: [Field.PVW, 'boolean'], - }, this); - } - - async _pickAt([x, y]) { - try { - let [color] = await this._picker.pick_color(x, y); - this._color.fromClutter(color); - this._view?.setColor(x, y, this.pvstyle ? this._color : color); - } catch(e) { - this.emit('end-pick', true); - } - } - - set preview(preview) { - if(xnor(preview, this._view)) return; - if(preview) { - this._view = this.pvstyle ? new ColorLabel() : new ColorIcon(); - this._menu = new ColorMenu(this); - this._menu.connectObject('color-selected', (_a, color) => this._emitColor(color), - 'open-state-changed', (_a, open) => setCursor(open ? 'DEFAULT' : this._view?.cursor_type), getSignalHolder(this)); - } else { - omit(this, '_view', '_menu'); - } - setCursor(preview === null ? 'DEFAULT' : this._view?.cursor_type ?? 'CROSSHAIR'); - } - - _emitColor(color) { - this.emit('notify-color', color || this._color); - if(!this.persist || this.once) this.emit('end-pick', false); - } - - vfunc_enter_event(event) { - this._pickAt(event.get_coords()); - return Clutter.EVENT_PROPAGATE; - } - - vfunc_motion_event(event) { - this._pickAt(event.get_coords()); - return Clutter.EVENT_PROPAGATE; - } - - _onMoveKeyPressed(keyval) { - let dx = 0, dy = 0; - switch(keyval) { - case Clutter.KEY_a: - case Clutter.KEY_h: - case Clutter.KEY_Left: dx = -1; break; - case Clutter.KEY_w: - case Clutter.KEY_k: - case Clutter.KEY_Up: dy = -1; break; - case Clutter.KEY_d: - case Clutter.KEY_l: - case Clutter.KEY_Right: dx = 1; break; - case Clutter.KEY_s: - case Clutter.KEY_j: - case Clutter.KEY_Down: dy = 1; break; - } - this._pointer.notify_relative_motion(global.get_current_time(), dx, dy); - } - - vfunc_key_press_event(event) { - let key = event.get_key_symbol(); - if(this.menukey && key === Clutter[`KEY_${this.menukey}`]) { - this._menu?.summon(); - } else if(key === Clutter.KEY_Escape || this.quitkey && key === Clutter[`KEY_${this.quitkey}`]) { - this.emit('end-pick', true); - return Clutter.EVENT_PROPAGATE; - } else { - this._onMoveKeyPressed(key); - } - return super.vfunc_key_press_event(event); - } - - vfunc_button_press_event(event) { - switch(event.get_button()) { - case Clutter.BUTTON_PRIMARY: this._emitColor(); break; - case Clutter.BUTTON_MIDDLE: this._menu?.summon(); break; - default: this.emit('end-pick', true); break; - } - return Clutter.EVENT_PROPAGATE; - } -} - -class ColorButton extends PanelMenu.Button { - static { - GObject.registerClass(this); - } - - constructor(fulu, callback, ...args) { - super(...args); - this._buildWidgets(callback); - this._bindSettings(fulu); - this._addMenuItems(); - } - - _buildWidgets(callback) { - this._callback = callback; - this.menu.actor.add_style_class_name('color-picker-menu'); - this.add_style_class_name('color-picker-systray'); - this._icon = new TrayIcon(); - this.add_actor(this._icon); - } - - _bindSettings(fulu) { - this._fulu = fulu.attach({ - format: [Field.FMTS, 'uint'], - enable_fmt: [Field.FMT, 'boolean'], - icon_name: [Field.TICN, 'string'], - menu_size: [Field.MSIZ, 'uint'], - }, this).attach({ - collect: [Field.CLCT, 'value', x => x.deepUnpack()], - history: [Field.HIST, 'value', x => x.deepUnpack()], - menu_style: [Field.MSTL, 'boolean'], - }, this, 'section'); - } - - set section([k, v, out]) { - this[k] = out ? out(v) : v; - this._menus?.section.setList(...this.getSection()); - } - - set format(format) { - this._format = format; - this._menus?.format.setSelected(format); - } - - set icon_name(path) { - path ? this._icon.set_gicon(Gio.Icon.new_for_string(path)) : this._icon.set_icon_name('color-select-symbolic'); - } - - set enable_fmt(enable_fmt) { - this._enable_fmt = enable_fmt; - if(enable_fmt) ['sep0', 'format'].forEach(x => this._menus?.[x].show()); - else ['sep0', 'format'].forEach(x => this._menus?.[x].hide()); - } - - _addMenuItems() { - this._menus = { - format: new RadioItem(_('Default format'), omap(Formats, ([k, v]) => [[v, k]]), this._format, x => this._fulu.set('format', x, this)), - sep0: new PopupMenu.PopupSeparatorMenuItem(), - section: new ColorSection(...this.getSection()), - sep1: new PopupMenu.PopupSeparatorMenuItem(), - prefs: new IconItem('color-picker-setting', { - pick: [() => { this.menu.close(); this._callback(); }, 'find-location-symbolic'], - star: [() => this._fulu.set('menu_style', !this.menu_style, this), this.menu_style, 'semi-starred-symbolic', 'starred-symbolic'], - gear: [() => { this.menu.close(); getSelf().openPreferences(); }, 'emblem-system-symbolic'], - }), - }; - Object.values(this._menus).forEach(x => this.menu.addMenuItem(x)); - this.enable_fmt = this._enable_fmt; - } - - getSection() { - return [this.menu_style ? this.collect.map(x => [true, x]) : this.history.map(x => [this.collect.includes(x), x]), x => this._starColor(x)]; - } - - _starColor(color) { - let collect = this.collect.includes(color) - ? this.collect.filter(x => x !== color) - : [color].concat(this.collect).slice(0, this.menu_size); - this._fulu.set('collect', new GLib.Variant('at', collect), this); - } - - _addHistory(color) { - let history = [color, ...this.history].slice(0, this.menu_size); - this._fulu.set('history', new GLib.Variant('at', history), this); - } - - vfunc_event(event) { - if(event.type() === Clutter.EventType.BUTTON_PRESS && event.get_button() === Clutter.BUTTON_PRIMARY) { - this._callback(); - return Clutter.EVENT_STOP; - } - return super.vfunc_event(event); - } -} - -class ColorPicker extends Destroyable { - constructor(gset) { - super(); - this._buildWidgets(gset); - this._bindSettings(); - } - - _buildWidgets(gset) { - this._picked = []; - this._fulu = new Fulu({}, gset, this); - this._src = manageSource(this, () => omit(this, 'systray', '_area'), { - keys: [x => x && Main.wm.removeKeybinding(Field.KEYS), x => x && Main.wm.addKeybinding(Field.KEYS, - this._fulu.gset, Meta.KeyBindingFlags.NONE, Shell.ActionMode.ALL, () => this.summon())], - }); - } - - _bindSettings() { - this._fulu.attach({ - format: [Field.FMTS, 'uint'], - enable_fmt: [Field.FMT, 'boolean'], - systray: [Field.STRY, 'boolean'], - auto_copy: [Field.COPY, 'boolean'], - shortcut: [Field.KEY, 'boolean'], - menu_size: [Field.MSIZ, 'uint'], - notify_style: [Field.NTFS, 'uint'], - enable_notify: [Field.NTF, 'boolean'], - }, this); - } - - set shortcut(shortcut) { - this._src.keys.refreshSource(shortcut); - } - - set systray(systray) { - if(xnor(systray, this._btn)) return; - if(systray) this._btn = Main.panel.addToStatusArea(getSelf().uuid, new ColorButton(this._fulu, () => this.summon(), 0.5)); - else omit(this, '_btn'); - } - - summon() { - if(this._area) return; - this._btn?.add_style_pseudo_class('busy'); - this._area = new ColorArea({ format: this.enable_fmt ? this.format : null, fulu: this._fulu }); - this._area.connectObject('end-pick', () => this.dispel(), 'notify-color', this.inform.bind(this), getSignalHolder(this)); - } - - dispel() { - if(!this._area) return; - this._btn?.remove_style_pseudo_class('busy'); - if(this.auto_copy && this._picked.length) setClipboard(this._picked.join(' ')); - this._picked.length = 0; - omit(this, '_area'); - } - - inform(_a, color) { - let text = color.toText(); - this._picked.push(text); - this._btn?._addHistory(color.toRaw()); - if(!this.enable_notify) return; - if(this.notify_style === Notify.MSG) { - Main.notify(getSelf().metadata.name, _('%s is picked.').format(text)); - } else { - let icon = Gio.BytesIcon.new(genColorSwatch(color.toText(Format.HEX))); - Main.osdWindowManager.show(global.display.get_current_monitor(), icon, text); - } - } - - pickAsync() { - return new Promise((resolve, reject) => { - try { - if(this._area) throw gerror('FAILED', 'Cannot start picking'); - this._btn?.add_style_pseudo_class('busy'); - this._area = new ColorArea({ once: true, fulu: this._fulu }); - this._area.connectObject('end-pick', (_a, except) => { this.dispel(); if(except) raise('aborted'); }, - 'notify-color', (_a, color) => resolve(color.toText(Format.HEX)), getSignalHolder(this)); - } catch(e) { - reject(e); - } - }); - } -} - -export default class Extension extends BaseExtension { - $klass = ColorPicker; - // API: Main.extensionManager.lookup('color-picker@tuberry').stateObj.pickAsync().then(log).catch(log) - pickAsync() { - if(!this.$delegate) raise('disabled'); - return this.$delegate.pickAsync(); - } -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/fubar.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/fubar.js deleted file mode 100644 index cd55509..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/fubar.js +++ /dev/null @@ -1,102 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'; -import { loadInterfaceXML } from 'resource:///org/gnome/shell/misc/fileUtils.js'; -import { TransientSignalHolder } from 'resource:///org/gnome/shell/misc/signalTracker.js'; -import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import { vmap, raise } from './util.js'; - -// roll back to the previous workaround for the read-only signalTracker since 45.beta -// TODO: wait for https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2542 -const _isDestroyable = x => GObject.type_is_a(x, GObject.Object) && GObject.signal_lookup('destroy', x); - -export { _ }; -export const getSelf = () => Extension.lookupByURL(import.meta.url); -export const omit = (o, ...ks) => ks.forEach(k => { o[k]?.destroy?.(); o[k] = null; }); -export const getSignalHolder = o => [o, o.$signal_holder].find(x => _isDestroyable(x)) ?? raise('undestroyable'); - -export class Destroyable extends EventEmitter { - $signal_holder = new TransientSignalHolder(this); - - destroy() { - this.emit('destroy'); - omit(this, '$signal_holder'); - } -} - -export function manageSource(host, doom, obj) { - if(doom) new SourceManager(host, doom); - if(obj) return vmap(obj, v => new SourceManager(host, ...v)); -} - -export function lightProxy(callback, obj) { - let BUS_NAME = 'org.gnome.SettingsDaemon.Color', - colorInfo = Gio.DBusInterfaceInfo.new_for_xml(loadInterfaceXML(BUS_NAME)), - proxy = new Gio.DBusProxy({ - g_name: BUS_NAME, - g_connection: Gio.DBus.session, - g_object_path: '/org/gnome/SettingsDaemon/Color', - g_interface_name: colorInfo.name, - g_interface_info: colorInfo, - }); - proxy.connectObject('g-properties-changed', callback, getSignalHolder(obj)); - proxy.init_async(GLib.PRIORITY_DEFAULT, null).catch(logError); - - return proxy; -} - -export class BaseExtension extends Extension { - enable() { - this.$delegate = new this.$klass(this.getSettings()); - } - - disable() { - omit(this, '$delegate'); - } -} - -export class SourceManager { - constructor(host, remove, add) { - host.connectObject('destroy', () => this.removeSource(), getSignalHolder(host)); - this.removeSource = () => { remove(this._delegate); this._delegate = null; }; - this.addSource = (...args) => (this._delegate = add(...args)); - } - - refreshSource(...args) { - this.removeSource(); - return this.addSource(...args); - } -} - -export class Fulu { - constructor(prop, gset, obj, cluster) { - this.prop = new WeakMap(); - this.gset = typeof gset === 'string' ? new Gio.Settings({ schema: gset }) : gset; - this.attach(prop, obj, cluster); - } - - get(prop, obj) { - return (([key, type]) => this.gset[`get_${type}`](key))(this.prop.get(obj)[prop]); - } - - set(prop, value, obj) { - (([key, type]) => this.gset[`set_${type}`](key, value))(this.prop.get(obj)[prop]); - } - - attach(props, obj, cluster) { // cluster && props <- { fulu: [key, type, output] } - this.prop.has(obj) ? Object.assign(this.prop.get(obj), props) : this.prop.set(obj, props); - let callback = cluster ? x => { obj[cluster] = [x, this.get(x, obj), this.prop.get(obj)[x][2]]; } : x => { obj[x] = this.get(x, obj); }; - Object.entries(props).forEach(([k, [x]]) => { callback(k); this.gset.connectObject(`changed::${x}`, () => callback(k), getSignalHolder(obj)); }); - return this; - } - - detach(obj) { - this.gset.disconnectObject(getSignalHolder(obj)); - } -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/de_DE/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/de_DE/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index a2cfffaeca5bd098da2971d5f52cc598bdbcb502..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1111 zcmYk4zmF6*6vv%#Nni;{Kp;}2c!`1pf>~zwKsxqvfrI;@li1wqZi9f%JM(tN?2J9K zJsi7LibyG_BSiu!P0F-EibS_%`jj*@6#NMke7(DHSo58apZ)Cj9gkm}TKZj}oq)c9 zeuYj#uc6T5kLGhN@D$?f;1}TDf)YG}xLVBnMf@B1CB`3vUx81+3*g`2=ivX~*WgQV z3wi^cL3|6Fod)lL!G{LVg1>-x#29%E5>t)E zrj~<(sj~b~@xi;$jh(l0EV}#K;wR(P5KFu=nw%dOEOz%dM31dg&a?JZnv}(UZmdsg zPu|SxiLgESoKdGRHVh|)ss={dl;qH}ouw(Ai5&YFJ0_yWNyp<8RO(!9HN zUemX0)Vi?R5V#QswN061?J_=?{*@R0@MgFqr;(`?Th`)^v4~|&QcqZA7}+UlM-R;a z(+ZjI$HP5Yw;tbb=_YHL(TVNop3>ux}^2m z&FrAgmb3$=u+MB%<^}A|?{09YG~GW?=%Li0z@PZQGuuMeLzmgKeHXLe{dkYWmFChQ` diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/es_ES/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/es_ES/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index 476ee28dc287398906250cd4909ebe4a8915a28c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1187 zcmYk4&x=$?5XakSqK--Y0ivKtdk`bi>&%Lxv#v(hT_ZSg*d4`d&3m;o?e^<_boWzd zPYQt`o&$;}k3ufNgWz@k2k{^|=ruUOH_Y+DYjD_Dgg8>9FEnn}y5E~x6EePfwRG^RRXpmTMl8U)pIZQ1DF zRLdB-j=xHg+j6!!+fvQ*s&!VjPPflAPc~%hrjx#vOHyE&IuEUB|hO@-$iz3-#aj;o;L`;lsmcGO*z+!}U_` zX0Taml9co`evt$vextrNIuicYq@_@i(d(4y@hkhy9&S$C9Pv3Mk;5y=vZ-~p7@{@~ zi@2$Y;wH&SY#oq~$caET8L?37GH28sq9gLSgud5x9#lGhBmM{Q22Z2_ diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/it_IT/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/it_IT/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index 0cbd514447dd23fe711342cac88d9a0c4445028b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 936 zcmYk4%We}f6ow6y+i+{kRiaW4iwY2On2fS$Ckj&OO_drNH3RC_opC1y#~#^EAv^%; z3$TWF>6Q&Iz?z3(!9VHM((&ixv40=W??1Cs-x=C1#2g|ZW)Qy+b(_A#*d1^NybI2s zumN5{-T`O9<&!)E?;+m>r@;Yu8ytgAz;9p^@dNP)`R~h&-3R}I^WZ=51~>=t2jBu& zpOd0{2)+RygBkb~)L^~u5QOBUO`)&va}5ExiQY{ROIU=s*sdeFdU0aGlk!xl{F5vi zY|V&0Eva(yK*`UisUQ2`#F%ya8|jdF6vNfrhq_tUs_W zbAX~k;ms8?6$ zC}~DJvVu16`cf7A?WpuTvnfTrZN7u5>pgr`1esD2Cruu=c)UdMQrc?0ijz2wwuBEn zbHaEnP!V=+2~&2nyLMhnvk^xt*3|dp*|@?XL4FCZD=n01Q$7&R z%g}kBt@Fk6b@f^M((yHu+d`Q#rNuoc@A3_4q&qI6XJw%RC5=`iiF$hEgy!qk4Sh$_-%<#tm diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/nl/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/nl/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index 18d0272797eacc23fd2a87135756d4f36a4495c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1164 zcmYL{L5~zg6vs;hlo1e!7)d-72NDRWb!G_!XI%wkS;;am*%^%SR@42ayXfkwPSxv$ z;lu&r!83`5kDv#?12>KwJQ{-+4}Jj?4*aWkU^{vJ>sR&az5nZaf1TL>RNy%R`yBQd zb{zH}EIs}AcJ~J03HaZDN5SnSHTXXKX1UKx|0nQctp5xi1D}ECz~8~c;Gf`U;6I>) zy@s8FUm@8^@Co<{_zXKL!5>FM-GQ@9NzI2k?IcQ9^tK zI{-^LQoen#Logf@2TtwF{Z~W+675 zo>`JjpdCZ^-@0)TIp~ELO*X}C&t{GzY`l|^7na1G$#pTN5KUxqENh>Wn3O(n*0N;Z z)e|YbibmNyP+(cuSvy{tX1>?V$!ne3aYN@(A%a4!qg}hCRf+mBC4q$%HH^n+D6M= z{B_MVl&k&Kf$D#$2AAaE!ti4Me1Emy@7>ao)ih`qt%k^<{EiId$O-%ToNSa|Aqnd? z#&~6p*jgLAlKJ{;oODI23sO_k^-wzR=-nDz+Z){+ZS1u&Sn2n^^)CHTHC;3i#OUaY z#%kl%WLD}BiP!H=Z>Y^mTVUO(8C&8%cEV2G03LRR910 diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/pt_PT/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/pt_PT/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index a29e0c207f9709ad4ee869cf7eeedefeea7f85c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1801 zcmY+Dzi%8x6vqb$5FZdA5CRCqAQ6O#);?Quh>stNaSmkROHTHY4xzc-=e>z%ch)m= z=WLJ=1)@MuP$1DzL=-5ID58ia1yXeX0ir-cqNPkpL&5j$?Vat>&3!bpZ{~g9oA>@c zdF*?EaT@a_%s((+!Tja{{9zn_P>3hMIq+fdGJq7U-pX2X1_$7#|#J3>l=(~D-6J(vg zfG>c*fqec?um#=+Pl0d38SA|Ou7U-~cDKMY;63nF@E?#<&UfNymwN3j87xe)Oa~bcRGyL-?OgQ@vC&A={&eX} zADk-1Mr?DjsrqC@XZu5O$p*axS3%oc`cN7Ym$xs9E;+A#pghRTCM3F*N0paymrB1N zwg=XQco^6{s~0R&h5N>?T|;Nso zokZ^sQy=wgOE$Wfqb)p6Wq(lxYRTp1@^aK%jh5b$ODnCF)w9i|X0x%We298Z<=!ad ztR*`-9g>k(v{CY%tXkL+78lY?X|sSrcn^p2bf{8_dZeXyUpwlR1>^+8vsf6V^S8OIoTu>a$Gs1t^9OdUYKL6Z&SRV4U0d>eUx$WR z$Lpi2JsFCT50xm?_4+`KXdd4Rt(;V|0>`@s5^IG@C*{32Bx#3}`o>|ZYrIfSNmbzO z__UYGprF+F=kc#7_qCu$*e=}oW`vv$mC@Jv+fR1-iR)e_78Qqz&Q#R`B-%m4T~JjU zw0+RV%7l=wNkdF-;9lrhoGoSzQ8z;+Zx7yZ3F@6L8C3H5I@YXl|6L W0B)#B^h&!UR<2HqI?y$~EB*&$L+*|M diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/tr_TR/LC_MESSAGES/gnome-shell-extension-color-picker.mo b/.local/share/gnome-shell/extensions/color-picker@tuberry/locale/tr_TR/LC_MESSAGES/gnome-shell-extension-color-picker.mo deleted file mode 100644 index fbec7a4cc3f5a8323f4f6bef76e21ed4b7b63800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1153 zcmaiyy^j+|7{-T>5aNV{5Jd_k#Y;hfqBU!qNY0W20^C`r;GAWf2r4w*o%0U6JF}XZ z4J-`}5=H8yNFq_Di6Xg4b)Airzu-z5M8|(X3ZC)#fR2%#{mtk5KJV;2J#qL~hIS14 z3VH~A3cY}Q3lHqAwZIb?Ujjb{hbwaM5XR+d-L1xtz)vv$3wRv-13U}<4Sodff?t5o zzzX_*HE$5?6y_g*pMk%FC&7O}@9{s-=idcC2cLsJ-b>K?J9?P04)`VL^KXHt!P_8G zun(d4ARp^}=pgg~gyRfbmazcV@E^3J(2-?t^*LinS}J9niKNNCubeKplQGZpnqpnn zY+dn5E~qr(XDROP4{dFo;Wg`zdhAE-Nqe3TwjZ$q~ zTsd-jnUDGK#!S!jqBXHU~IUuIftW&`c=w{LL_6J@~}u)M*HN(bLt^Bjaucq8b(+2jLd{*TTllpeK|td)4;v&sU{Wr`hSk3c~}kV*Z!R6WL@#p)$&JQmKkcu5`^YDr=r| zHvdh@`?)AYEonOc7Z1a*k$)cr3MlbXB<}0=%KT63XySt!S+Fas4qlhcCEGHNzg{Gf z!PH{Le&G3H7B6Ph*9p7DGbAmLelfGW)_Jw(ZQp8!`y;EB;rl+#Th>>e4eOz@LOyv+ g6J1xXVtt|JJN0~rIOcgq5``lUUpywam}MyQ6{0(lz_+=GtxRQ4MiUjlc7>%osfjvj|V()}&O-4Ff%QofrY>G>I?e82hYv`G7Fd~N_K z?iHWa{`zY^xB6`I_doFG5s>;!g5*O6d;mNOz5tGa)ZaWv^?vu){{^4GoZp9<;1-bf zKLn|-4v_M7gY*d@yX+fK-X|_zNW}vFpAPws<$a6Xqk71B6_*~_><=*j3HRyuP zX zw#^W#jXUDFW%Hyh9EXP++rll}wGfg>=q``MRWl|Wwp~Qkl;QHIWg`s>n`*lu=$(DK z=v=xM@SMrq=DO$&Cx!Va>Sdjw?); zCoD~{=CTgeO!E$rcB)y6P&FR4tptx4da~V8ZH=|YE!&NxToOusGHQq;A7mToh4e25 zb2aJ;w1+U=jIp@r;;1WlLZ~KOvQnmIQ0F_s?{g;=iF4KAw=$#kQ7x#cw=!ca4t18D z=8nE!u!OE5oU$)>twES6l1qiHq%e`(Ofi%CUM_2;l8WJ~ZCjn?R(TEYR2>b7@98io zRl?dQczYV!yI`enw(p>=$Kv=rD|LjO$fAtBDcxnugH}juwyixP;wn2eWjFb6nIRrC zt%OjVxG)Swbm4>0vQjowDIX@A*KG;3h$OsM8l0G}DO*!9M`^P{JkZ>vwBRh1U)ip@ zBE;*0b+t;cUa76;wXcSPwVQ+W!C+vQ>bOdq4eJdRu7>!^gBcU1u<^QvKr@z7V?t>Y zY9ho<%M?p%A-+HU(YD4w!_J2A9sRY{!N4}lq?4qyrIV20qK%rQq3Y)AbdYUFxNp4I z_O?=gCytavg{_3mh^66tgm`_s?gp5gneq5B;_`;W=qyw`UeL2~3&@w>BLZgAnogf}wn4P9rY{BUt{!W*BJvpFUQ zFBOK)m(Fw-&-F1cJ6sqUmLqfCcrWvT$HK)qR=AQcC9*`J0<%rFTFuOjCZ8hJ2C#E%+1Jbe_=LLIN6QArP9&D++lh4 zz=|J64jhuXDLHXYUe2+FYZpL^m5t?P{{zf Gio.Icon.new_for_string(`${ROOT}/icons/hicolor/scalable/status/${x}.svg`); - -export class TrayIcon extends St.Icon { - static { - GObject.registerClass(this); - } - - constructor(icon_name = '', fallback) { - super({ style_class: 'system-status-icon', icon_name }); - if(fallback) this.set_fallback_gicon(gicon(icon_name)); - } -} - -export class StButton extends St.Button { - static { - GObject.registerClass(this); - } - - constructor(param, callback) { - super(param); - this.connect('clicked', callback); - this.set_can_focus(true); - } -} - -export class IconButton extends StButton { - static { - GObject.registerClass(this); - } - - constructor(param, callback, icon_name = '') { - super(param, callback); - this.set_child(new St.Icon({ style_class: 'popup-menu-icon', icon_name })); - } - - setIcon(icon) { - this.child.set_icon_name(icon); - } -} - -export class StatusButton extends IconButton { - static { - GObject.registerClass(this); - } - - constructor(param, callback, status, on, off) { - super(param, callback, status ? on : off); - this.connect('clicked', () => this.setIcon({ [on]: off, [off]: on }[this.child.get_icon_name()])); - } -} - -export class IconItem extends PopupMenu.PopupBaseMenuItem { - static { - GObject.registerClass(this); - } - - constructor(style_class, icons) { - super({ activate: false }); - this._icons = vmap(icons, x => new (x.length > 2 ? StatusButton : IconButton)({ x_expand: true, style_class }, ...x)); - let box = new St.BoxLayout({ x_align: Clutter.ActorAlign.FILL, x_expand: true }); - Object.values(this._icons).forEach(x => box.add_child(x)); - this.add_child(box); - } - - setViz(icon, viz) { - this._icons[icon]?.[viz ? 'show' : 'hide'](); - } -} - -export class SwitchItem extends PopupMenu.PopupSwitchMenuItem { - static { - GObject.registerClass(this); - } - - constructor(text, active, callback, param) { - super(text, active, param); - this.connect('toggled', (_x, y) => callback(y)); - } -} - -export class MenuItem extends PopupMenu.PopupMenuItem { - static { - GObject.registerClass(this); - } - - constructor(text, callback, param) { - super(text, param); - this.connect('activate', callback); - } - - setLabel(label) { - this.label.set_text(label); - } -} - -export class RadioItem extends PopupMenu.PopupSubMenuMenuItem { - static { - GObject.registerClass(this); - } - - constructor(name, enums, enum_, callback) { - super(''); - this._enum = enums; - this._name = name; - Object.entries(enums).forEach(([k, v]) => this.menu.addMenuItem(new MenuItem(v, () => callback(k)))); - this.setSelected(enum_); - } - - setSelected(m) { - if(!(m in this._enum)) return; - this.label.set_text(`${this._name}:${this._enum[m]}`); - this.menu._getMenuItems().forEach(x => x.setOrnament(x.label.text === this._enum[m] ? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE)); - } -} - -export class DRadioItem extends PopupMenu.PopupSubMenuMenuItem { - static { - GObject.registerClass(this); - } - - constructor(name, list, index, click, select) { - super(''); - this._name = name; - this._onClick = click; - this._onSelect = select || (x => this._list[x]); - this.setList(list, index); - } - - setSelected(index) { - this._index = index; - this.label.set_text(`${this._name}:${this._onSelect(this._index) || ''}`); - this.menu._getMenuItems().forEach((y, i) => y.setOrnament(index === i ? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE)); - } - - setList(list, index) { - let items = this.menu._getMenuItems(); - let diff = list.length - items.length; - if(diff > 0) for(let a = 0; a < diff; a++) this.menu.addMenuItem(new MenuItem('', () => this._onClick(items.length + a))); - else if(diff < 0) do items.at(diff).destroy(); while(++diff < 0); - this._list = list; - this.menu._getMenuItems().forEach((x, i) => x.setLabel(list[i])); - this.setSelected(index ?? this._index); - } -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/metadata.json b/.local/share/gnome-shell/extensions/color-picker@tuberry/metadata.json deleted file mode 100644 index cd576d7..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Simple color picker for gnome shell\n\nFor support, please report any issues via the homepage link below.", - "gettext-domain": "gnome-shell-extension-color-picker", - "name": "Color Picker", - "settings-schema": "org.gnome.shell.extensions.color-picker", - "shell-version": [ - "45" - ], - "url": "https://github.com/tuberry/color-picker", - "uuid": "color-picker@tuberry", - "version": 38 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/prefs.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/prefs.js deleted file mode 100644 index 0e2511b..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/prefs.js +++ /dev/null @@ -1,99 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; -import Gdk from 'gi://Gdk'; -import GObject from 'gi://GObject'; - -import * as UI from './ui.js'; -import { Field } from './const.js'; - -const { _ } = UI; - -class KeyBtn extends UI.DlgBtnBase { - static { - GObject.registerClass(this); - } - - constructor() { - super(new Gtk.ShortcutLabel({ disabled_text: _('(Key)') }), null, true); - } - - _buildDialog() { - let content = new Adw.StatusPage({ title: _('Press any key.'), icon_name: 'preferences-desktop-keyboard-symbolic' }); - this._dlg = new Adw.Window({ modal: true, hide_on_close: true, width_request: 480, height_request: 320, content }); - let eck = new Gtk.EventControllerKey(); - eck.connect('key-pressed', this._onKeyPressed.bind(this)); - this._dlg.add_controller(eck); - } - - _onClick() { - if(!this._dlg) this._buildDialog(); - this._dlg.present(); - let root = this.get_root(); - if(this._dlg.transient_for !== root) this._dlg.set_transient_for(root); - return Promise.reject(new Error()); // compatible with super - } - - _setValue(v) { - this._value = v; - this._showValue(); - } - - _showValue() { - this._btn.child.set_accelerator(this._value); - } - - _onKeyPressed(_w, keyval, keycode, state) { - let mask = state & Gtk.accelerator_get_default_mod_mask() & ~Gdk.ModifierType.LOCK_MASK; - if(mask || keyval !== Gdk.KEY_Escape) this.value = Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask); - this._dlg.close(); - } -} - -class ColorPickerPrefs extends Adw.PreferencesGroup { - static { - GObject.registerClass(this); - } - - constructor(gset) { - super(); - this._buildWidgets(gset); - this._buildUI(); - } - - _buildWidgets(gset) { - this._blk = UI.block({ - MKEY: ['value', new KeyBtn()], - QKEY: ['value', new KeyBtn()], - TICN: ['value', new UI.Icon()], - COPY: ['active', new Gtk.CheckButton()], - NTF: ['active', new Gtk.CheckButton()], - FMT: ['active', new Gtk.CheckButton()], - PVW: ['active', new Gtk.CheckButton()], - KEY: ['active', new Gtk.CheckButton()], - STRY: ['active', new Gtk.CheckButton()], - PRST: ['active', new Gtk.CheckButton()], - NTFS: ['selected', new UI.Drop([_('MSG'), _('OSD')])], - MSIZ: ['value', new UI.Spin(1, 16, 1, _('history size'))], - FMTS: ['selected', new UI.Drop(['HEX', 'RGB', 'HSL', 'hex', 'HSV', 'CMYK'])], - PVWS: ['selected', new UI.Drop([_('Icon'), _('Label')], _('preview style'))], - }, gset); - this._blk.KEYS = new UI.Keys(gset, Field.KEYS); - } - - _buildUI() { - [ - [this._blk.COPY, [_('Automatically copy'), _('copy the color to clipboard after picking')]], - [this._blk.FMT, [_('Default format'), _('hex here means poundless HEX such as “8fd0da”')], this._blk.FMTS], - [this._blk.KEY, [_('Shortcut to pick'), _('press arrow keys / wasd / hjkl to move by pixel')], this._blk.KEYS], - [this._blk.NTF, [_('Notification style'), _('notify the color after picking')], this._blk.NTFS], - [this._blk.PRST, [_('Persistent mode'), _('right click or press Esc key to quit')], this._blk.QKEY], - [this._blk.PVW, [_('Enable preview'), _('middle click or press Menu key to open menu')], this._blk.PVWS, this._blk.MKEY], - [this._blk.STRY, [_('Enable systray'), _('right click to open menu')], this._blk.TICN, this._blk.MSIZ], - ].forEach(xs => this.add(new UI.PrefRow(...xs))); - } -} - -export default class PrefsWidget extends UI.Prefs { $klass = ColorPickerPrefs; } diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/color-picker@tuberry/schemas/gschemas.compiled deleted file mode 100644 index 72e556e4c326b6bb2a8cdcc30725e861783c1801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1323 zcmZuwO=#3W7#&;J{&%;w)q)7UH9@jl5O1OXkrWx1lHAGv`a zm7Tx~LaX6AOESbvVT|yJ!F7i-6u`Y1`oR4;3_`b2geFSB(F}|?9-SZQ1T&vOu`F8P zufUtRjUoEfMfd_Q1)zEC$uNED68tgnNud4j)I!XNac~Vd@#3_OL(TXr;3lxyTwpJ(x)DU zKL(xvK1|>IPM?}_Cc$R_XLR;0ed-bTSHQDCb-MJ6K6MZLJ75Wf7j82Ztq0(*z-t0q zUxr@Nr>6f5{0eyVaE~R^n*Ij7_dso~uS%bqb#8&Tft}s3hdwpywg>(Obo^dlqfgB^ zD4r+)^Q%Aj>sm9<61-Euf~?xHr>tra*6sZcM*f(~fhp*$*hq{xHceCd_Pi&ps1}6E ziTCFl^JdzOczV)N=uf@QRwkG|hc?mu)k7bHJvIO!P2I0U;4WYoI0AG7>_zq``B_DpjI%luO4H=%BL}M6sWZsQkWu-eHew0Kiv=eI~3>uha zxlUR$y$` - - - - true - enable system tray - - - false - enable shortcut - - - true - enable notify - - - false - persistent mode - - - true - auto copy color to clipboard - - - true - enable preview - - - true - enable format - - - 0']]]> - shortcut to pick color - - - "" - key to open menu - - - "" - key to quit picking - - - [] - picked color history - - - [] - picked color collection - - - "" - systray dropper icon - - - - 0 - preview style: 0-Icon 1-Label - - - - 0 - default format: 0-HEX 1-RGB 2-HSL 3-Hex(RRGGBB) 4-HSV 5-CMYK - - - - 0 - notify style: 0-MSG 1-OSD - - - - 8 - menu item size - - - false - menu style: false-history true-collection - - - diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/stylesheet.css b/.local/share/gnome-shell/extensions/color-picker@tuberry/stylesheet.css deleted file mode 100644 index b34b2a4..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/stylesheet.css +++ /dev/null @@ -1,21 +0,0 @@ -.color-picker-label { - color: #000000; - padding: 0.3em; - min-width: 6em; - font-size: 1.4em; - border-radius: 0.4em; - background-color: #ffffff; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.5); -} - -.color-picker-button { - padding: 0 0.5em; -} - -.color-picker-systray:busy { - color: #629fea; -} - -.color-picker-setting:hover { - color: #4b92e7; -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/ui.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/ui.js deleted file mode 100644 index e7599c0..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/ui.js +++ /dev/null @@ -1,505 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import Adw from 'gi://Adw'; -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; -import GLib from 'gi://GLib'; -import Pango from 'gi://Pango'; -import GObject from 'gi://GObject'; - -import * as Gettext from 'gettext'; -import { Field } from './const.js'; - -import { fopen, raise, omap, noop, gprops, fquery } from './util.js'; -import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export { _ }; -export const _GTK = Gettext.domain('gtk40').gettext; -export const grgba = x => (c => [c.parse(x ?? ''), c])(new Gdk.RGBA()); -export const conns = (o, ...a) => a.forEach(([k, v]) => o.connect(k, v)); -export const getSelf = () => ExtensionPreferences.lookupByURL(import.meta.url); -export const block = (o, s) => omap(o, ([k, [x, y]]) => [[k, (s.bind(Field[k], y, x, Gio.SettingsBindFlags.DEFAULT), y)]]); - -Gio._promisify(Gtk.FileDialog.prototype, 'open'); -Gio._promisify(Gtk.FileDialog.prototype, 'select_folder'); - -export class Prefs extends ExtensionPreferences { - getPreferencesWidget() { - if(this.$klass) return new this.$klass(this.getSettings()); - } -} - -export class Box extends Gtk.Box { - static { - GObject.registerClass(this); - } - - constructor(children, param) { - super({ valign: Gtk.Align.CENTER, ...param }); - children?.forEach(x => this.append(x)); - this.add_css_class('linked'); - } -} - -export class Spin extends Gtk.SpinButton { - static { - GObject.registerClass(this); - } - - constructor(l, u, s, tip) { - super({ tooltip_text: tip || '', valign: Gtk.Align.CENTER }); - this.set_adjustment(new Gtk.Adjustment({ lower: l, upper: u, step_increment: s })); - } -} - -export class Drop extends Gtk.DropDown { - static { - GObject.registerClass(this); - } - - constructor(args, tip) { - super({ model: Gtk.StringList.new(args), valign: Gtk.Align.CENTER, tooltip_text: tip || '' }); - } -} - -export class Font extends Gtk.FontDialogButton { - static { - GObject.registerClass({ - Properties: gprops({ - value: ['string', ''], - }), - }, this); - } - - constructor(param) { - super({ valign: Gtk.Align.CENTER, dialog: new Gtk.FontDialog(), ...param }); - this.connect('notify::font-desc', () => this.notify('value')); - } - - get value() { - return this.get_font_desc().to_string(); - } - - set value(value) { - this.set_font_desc(Pango.FontDescription.from_string(value)); - } -} - -export class Color extends Gtk.ColorDialogButton { - static { - GObject.registerClass({ - Properties: gprops({ - value: ['string', ''], - }), - }, this); - } - - constructor(param) { - super({ tooltip_text: param?.title ?? '', valign: Gtk.Align.CENTER, dialog: new Gtk.ColorDialog(param) }); - this.connect('notify::rgba', () => this.notify('value')); - } - - get value() { - return this.get_rgba().to_string(); - } - - set value(value) { - let [ok, rgba] = grgba(value); - if(ok) this.set_rgba(rgba); - } -} - -export class IconLabel extends Gtk.Box { - static { - GObject.registerClass(this); - } - - constructor(fallback_icon) { - super({ spacing: 5 }); - this._icon = new Gtk.Image(); - this._label = new Gtk.Label(); - this._fallback_icon = fallback_icon; - [this._icon, this._label].forEach(x => this.append(x)); - } - - set_info(icon, text) { - this._label.set_label(text || _GTK('(None)')); - if(typeof icon !== 'string') this._icon.set_from_gicon(icon); - else this._icon.icon_name = icon || this._fallback_icon; - } -} - -export class AppDialog extends Adw.Window { - static { - GObject.registerClass({ - Signals: { - selected: { param_types: [GObject.TYPE_STRING] }, - }, - }, this); - } - - constructor(param) { - super({ title: _GTK('Select Application'), modal: true, hide_on_close: true, width_request: 280, height_request: 320 }); - this._buildContent(param); - } - - _buildList(param) { - let factory = new Gtk.SignalListItemFactory(); - conns(factory, ['setup', (_f, x) => x.set_child(new IconLabel('application-x-executable-symbolic'))], - ['bind', (_f, x) => x.get_child().set_info(...(y => [y.get_icon() || '', y.get_display_name()])(x.get_item()))]); - let model = new Gio.ListStore({ item_type: Gio.DesktopAppInfo }); - if(param?.no_display) Gio.AppInfo.get_all().forEach(x => model.append(x)); - else Gio.AppInfo.get_all().filter(x => x.should_show()).forEach(x => model.append(x)); - let expression = new Gtk.ClosureExpression(GObject.TYPE_STRING, x => `${x.get_executable()}:${x.get_display_name()}`, null); - this._filter = new Gtk.StringFilter({ expression }); - this._select = new Gtk.SingleSelection({ model: new Gtk.FilterListModel({ model, filter: this._filter }) }); - let list = new Gtk.ListView({ model: this._select, factory, single_click_activate: false, vexpand: true }); - list.connect('activate', () => this._onSelect()); - return new Gtk.ScrolledWindow({ child: list }); - } - - _buildContent(param) { - let eck = new Gtk.EventControllerKey(), - close = Gtk.Button.new_with_mnemonic(_GTK('_Close')), - select = Gtk.Button.new_with_mnemonic(_GTK('_Select')), - entry = new Gtk.SearchEntry({ halign: Gtk.Align.CENTER }), - box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }), - bar = new Gtk.SearchBar({ show_close_button: false, child: entry }), - header = new Adw.HeaderBar({ show_end_title_buttons: false, show_start_title_buttons: false }); - this._search = new Gtk.ToggleButton({ icon_name: 'system-search-symbolic' }); - - select.add_css_class('suggested-action'); - close.connect('clicked', () => this.close()); - select.connect('clicked', () => this._onSelect()); - eck.connect('key-pressed', (_w, k) => k === Gdk.KEY_Escape && this.close()); - entry.connect('search-changed', x => this._filter.set_search(x.get_text())); - this._search.bind_property('active', bar, 'search-mode-enabled', GObject.BindingFlags.BIDIRECTIONAL); - this.connect('close-request', () => this._search.set_active(false)); - bar.set_key_capture_widget(this); - bar.connect_entry(entry); - - this.add_controller(eck); - header.pack_start(close); - [select, this._search].forEach(x => header.pack_end(x)); - [header, bar, this._buildList(param)].forEach(x => box.append(x)); - this.set_content(box); - } - - _onSelect() { - this.close(); - this.emit('selected', this._select.get_selected_item().get_id()); - } -} - -export class DlgBtnBase extends Box { - static { - GObject.registerClass({ - Properties: gprops({ - value: ['string', ''], - }), - Signals: { - changed: { param_types: [GObject.TYPE_STRING] }, - }, - }, this); - } - - constructor(child, gtype, reset) { - super(); - this._btn = new Gtk.Button({ child }); - this._btn.connect('clicked', () => this._onClick().then(x => { this.value = x; }).catch(noop)); - if(gtype) this._buildDND(gtype); - if(reset) this._buildReset(); - this.prepend(this._btn); - this.value = ''; - } - - _buildReset() { - let clear = new Gtk.Button({ icon_name: 'edit-clear-symbolic', tooltip_text: _('Clear') }); - clear.connect('clicked', () => { this.value = ''; }); - this.append(clear); - } - - _buildDND(gtype) { - let drop = Gtk.DropTarget.new(gtype, Gdk.DragAction.COPY); - drop.connect('drop', this._onDrop.bind(this)); - let drag = new Gtk.DragSource({ actions: Gdk.DragAction.COPY }); - drag.connect('prepare', () => Gdk.ContentProvider.new_for_value(this._gvalue)); - [drop, drag].forEach(x => this._btn.add_controller(x)); - } - - _onDrop(_t, x) { - this.value = x; - } - - set value(v) { - if(typeof v === 'string' ? this._value === v : this._gvalue?.equal(v)) return; - this._setValue(v); - this.notify('value'); - this.emit('changed', this.value); - } - - get value() { - return this._value; - } - - vfunc_mnemonic_activate() { - this._btn.activate(); - } -} - -export class App extends DlgBtnBase { - static { - GObject.registerClass(this); - } - - constructor() { - super(new IconLabel('application-x-executable-symbolic'), null, true); - } - - _setValue(v) { - let type = typeof v === 'string'; - this._gvalue = type ? Gio.DesktopAppInfo.new(v) : v; - this._value = type ? v : v.get_id(); - this._showValue(); - } - - _showValue() { - if(this._gvalue) this._btn.child.set_info(this._gvalue.get_icon(), this._gvalue.get_display_name()); - else this._btn.child.set_info(''); - } - - _buildDialog() { - this._dlg = new AppDialog(); - this._dlg.connect('selected', x => { this.value = x._select.get_selected_item(); }); - } - - _onClick() { - if(!this._dlg) this._buildDialog(); - this._dlg.present(); - let root = this.get_root(); - if(this._dlg.transient_for !== root) this._dlg.set_transient_for(root); - return Promise.reject(new Error()); // compatible with super - } -} - -export class File extends DlgBtnBase { - static { - GObject.registerClass(this); - } - - constructor(param) { - super(new IconLabel('document-open-symbolic'), Gio.File.$gtype, true); - if(param?.select_folder) param.filter = { mime_types: ['inode/directory'] }; - if(param?.filter) this._filter = new Gtk.FileFilter(param.filter); - this._param = param; - } - - _buildDialog() { - this._dlg = new Gtk.FileDialog({ modal: true }); - if(this._param?.title) this._dlg.set_title(this._param.title); - if(this._filter) this._dlg.set_default_filter(this._filter); - } - - _onDrop(_t, value) { - if(!this._filter) { - this.value = value; - } else { - fquery(value, Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE).then(y => { - if(this._filter.match(y)) this.value = value; else raise(); - }).catch(() => { // ISSUE: folders - https://gitlab.gnome.org/GNOME/gtk/-/issues/5348 - this.get_root().add_toast(new Adw.Toast({ title: _('Mismatched filetype'), timeout: 5 })); - }); - } - } - - _setValue(v) { - let type = typeof v === 'string'; - this._gvalue = type ? fopen(v) : v; - this._value = type ? v : v.get_path() ?? ''; - this._showValue(this._value); - } - - _showValue(v) { - fquery(this._gvalue, Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FILE_ATTRIBUTE_STANDARD_ICON) - .then(x => this._setInfo(x.get_icon(), x.get_display_name(), v)).catch(() => this._setInfo('', null, v)); - } - - _onClick() { - if(!this._dlg) this._buildDialog(); - return this._dlg[this._param?.select_folder ? 'select_folder' : 'open'](this.get_root(), null); - } - - _setInfo(icon, text, value) { - if(value !== this.value) return; - this._btn.child.set_info(icon, text); - } -} - -export class Icon extends File { - static { - GObject.registerClass(this); - } - - constructor() { - super({ filter: { mime_types: ['image/svg+xml'] } }); - } - - _showValue(v) { - fquery(this._gvalue, Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FILE_ATTRIBUTE_STANDARD_ICON).then(x => { - let name = GLib.basename(x.get_display_name()).replace(/\.svg$/, ''); - let icon = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()).has_icon(name) ? name : ''; - this._setInfo(icon || x.get_icon(), x.get_display_name().replace(RegExp(/(-symbolic)*\.svg$/), ''), v); - }).catch(() => this._setInfo('', null, v)); - } -} - -export class Keys extends Gtk.Button { - static { - GObject.registerClass(this); - } - - constructor(gset, key) { - super({ valign: Gtk.Align.CENTER, has_frame: false }); - this._label = new Gtk.ShortcutLabel({ disabled_text: _GTK('New accelerator…') }); - this._label.set_accelerator(gset.get_strv(key).at(0)); - this.setShortcut = x => { gset.set_strv(key, [x]); this._label.set_accelerator(x); }; - this.connect('clicked', () => this._onClick()); - this.set_child(this._label); - this._buildDialog(); - } - - _buildDialog() { - let content = new Adw.StatusPage({ title: _GTK('New accelerator…'), icon_name: 'preferences-desktop-keyboard-shortcuts-symbolic' }); - this._dlg = new Adw.Window({ modal: true, hide_on_close: true, width_request: 480, height_request: 320, content }); - let eck = new Gtk.EventControllerKey(); - eck.connect('key-pressed', this._onKeyPressed.bind(this)); - this._dlg.add_controller(eck); - } - - _onClick() { - this._dlg.present(); - let root = this.get_root(); - if(this._dlg.transient_for !== root) this._dlg.set_transient_for(root); - } - - _onKeyPressed(_widget, keyval, keycode, state) { - let mask = state & Gtk.accelerator_get_default_mod_mask() & ~Gdk.ModifierType.LOCK_MASK; - if(!mask && keyval === Gdk.KEY_Escape) return this._dlg.close(); - if(!this.isValidBinding(mask, keycode, keyval) || !this.isValidAccel(mask, keyval)) return; - this.setShortcut(Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask)); - this._dlg.close(); - } - - keyvalIsForbidden(keyval) { - return [Gdk.KEY_Home, Gdk.KEY_Left, Gdk.KEY_Up, Gdk.KEY_Right, Gdk.KEY_Down, Gdk.KEY_Page_Up, - Gdk.KEY_Page_Down, Gdk.KEY_End, Gdk.KEY_Tab, Gdk.KEY_KP_Enter, Gdk.KEY_Return, Gdk.KEY_Mode_switch].includes(keyval); - } - - isValidBinding(mask, keycode, keyval) { - // From: https://gitlab.gnome.org/GNOME/gnome-control-center/-/blob/master/panels/keyboard/keyboard-shortcuts.c - return !(mask === 0 || mask === Gdk.SHIFT_MASK && keycode !== 0 && - ((keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || - (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || - (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || - (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) || - (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || - (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || - (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) || - (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) || - (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || - (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || - (keyval === Gdk.KEY_space && mask === 0) || this.keyvalIsForbidden(keyval)) - ); - } - - isValidAccel(mask, keyval) { - return Gtk.accelerator_valid(keyval, mask) || (keyval === Gdk.KEY_Tab && mask !== 0); - } -} - -export class PrefRow extends Adw.ActionRow { - static { - GObject.registerClass(this); - } - - constructor(...args) { - super(); - if(Array.isArray(args[0])) { - let [title, ...suffix] = args; - if(title.length) this.set_title(title[0]), this.set_subtitle(title[1] || ''); - if(suffix.length) suffix.forEach(x => this.add_suffix(x)), this.set_activatable_widget(suffix[0]); - } else { - let [prefix, title, ...suffix] = args; - if(title.length) this.set_title(title[0]), this.set_subtitle(title[1] || ''); - this.add_prefix(prefix); - if(prefix instanceof Gtk.CheckButton) { - this.set_activatable_widget(prefix); - if(suffix.length) { - suffix.forEach(x => { - this.add_suffix(x); - prefix.bind_property('active', x, 'sensitive', GObject.BindingFlags.DEFAULT); - x.set_sensitive(prefix.active); - }); - } - } else if(suffix.length) { - suffix.forEach(x => this.add_suffix(x)); - this.set_activatable_widget(suffix[0]); - } - } - } -} - -export class LazyEntry extends Gtk.Stack { - static { - GObject.registerClass({ - Properties: gprops({ - text: ['string', ''], - }), - Signals: { - changed: { param_types: [GObject.TYPE_STRING] }, - }, - }, this); - } - - constructor(holder, tip) { - super({ valign: Gtk.Align.CENTER, hhomogeneous: true }); - this._label = new Gtk.Entry({ hexpand: true, sensitive: false, placeholder_text: holder || '' }); - this._entry = new Gtk.Entry({ hexpand: true, enable_undo: true, placeholder_text: holder || '' }); - this._edit = new Gtk.Button({ icon_name: 'document-edit-symbolic', tooltip_text: tip || '' }); - this._done = new Gtk.Button({ icon_name: 'object-select-symbolic', tooltip_text: _('Click or press ENTER to commit changes'), css_classes: ['suggested-action'] }); - this.add_named(new Box([this._label, this._edit], { hexpand: true }), 'label'); - this.add_named(new Box([this._entry, this._done], { hexpand: true }), 'entry'); - this.bind_property('text', this._label, 'text', GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE); - this._edit.connect('clicked', () => this._onEdit()); - this._done.connect('clicked', () => this._onDone()); - this._entry.connect('activate', () => this._onDone()); - this.set_visible_child_name('label'); - } - - _onEdit() { - this._entry.set_text(this.text); - this.set_visible_child_name('entry'); - } - - _onDone() { - let text = this._entry.get_text(); - if(this.set_text(text)) this.emit('changed', text); - } - - set_text(text) { - let check = this.text !== text; - if(check) this._label.set_text(text); - this.set_visible_child_name('label'); - return check; - } - - get_text() { - return this.text; - } - - vfunc_mnemonic_activate() { - this.get_visible_child_name() === 'label' ? this._edit.activate() : this._done.activate(); - } -} diff --git a/.local/share/gnome-shell/extensions/color-picker@tuberry/util.js b/.local/share/gnome-shell/extensions/color-picker@tuberry/util.js deleted file mode 100644 index 3f3b6e6..0000000 --- a/.local/share/gnome-shell/extensions/color-picker@tuberry/util.js +++ /dev/null @@ -1,65 +0,0 @@ -// vim:fdm=syntax -// by tuberry - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Graphene from 'gi://Graphene'; -import Soup from 'gi://Soup/?version=3.0'; - -Gio._promisify(Gio.File.prototype, 'copy_async'); -Gio._promisify(Gio.File.prototype, 'delete_async'); -Gio._promisify(Gio.File.prototype, 'query_info_async'); -Gio._promisify(Gio.File.prototype, 'load_contents_async'); -Gio._promisify(Gio.File.prototype, 'make_directory_async'); -Gio._promisify(Gio.File.prototype, 'replace_contents_async'); -Gio._promisify(Gio.File.prototype, 'enumerate_children_async'); -Gio._promisify(Gio.Subprocess.prototype, 'communicate_utf8_async'); - -export const ROOT = GLib.path_get_dirname(import.meta.url.slice(7)); - -export const id = x => x; -export const noop = () => {}; -export const xnor = (x, y) => !x === !y; -export const raise = x => { throw new Error(x); }; -export const decode = x => new TextDecoder().decode(x); -export const encode = x => new TextEncoder().encode(x); -export const fpath = (...xs) => GLib.build_filenamev(xs); -export const vmap = (o, f) => omap(o, ([k, v]) => [[k, f(v)]]); -export const lot = x => x[Math.floor(Math.random() * x.length)]; -export const fopen = (...xs) => Gio.File.new_for_path(fpath(...xs)); -export const bmap = o => ({ ...o, ...omap(o, ([k, v]) => [[v, k]]) }); -export const array = (n, f = id) => Array.from({ length: n }, (_x, i) => f(i)); -export const omap = (o, f) => Object.fromEntries(Object.entries(o).flatMap(f)); -export const luminance = ({ r, g, b }) => Math.sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b); // Ref: https://stackoverflow.com/a/596243 -export const gerror = (x, y = '') => new Gio.IOErrorEnum({ code: Gio.IOErrorEnum[x] ?? x, message: y }); -export const gprops = o => omap(o, ([k, [x, ...ys]]) => [[k, GObject.ParamSpec[x](k, k, k, GObject.ParamFlags.READWRITE, ...ys)]]); -export const grect = (w, h, x = 0, y = 0) => new Graphene.Rect({ origin: new Graphene.Point({ x, y }), size: new Graphene.Size({ width: w, height: h }) }); -export const denum = (x, y = Gio.FILE_ATTRIBUTE_STANDARD_NAME) => x.enumerate_children_async(y, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_DEFAULT, null); -export const fquery = (x, ...ys) => x.query_info_async(ys.join(','), Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_DEFAULT, null); -export const fcheck = (...xs) => fquery(xs[0] instanceof Gio.File ? xs[0] : fopen(...xs), Gio.FILE_ATTRIBUTE_STANDARD_NAME); -export const fwrite = (x, y) => x.replace_contents_async(encode(y), null, false, Gio.FileCreateFlags.NONE, null); -export const fcopy = (x, y) => x.copy_async(y, Gio.FileCopyFlags.NONE, GLib.PRIORITY_DEFAULT, null, null); -export const dtouch = x => x.make_directory_async(GLib.PRIORITY_DEFAULT, null); -export const fdelete = x => x.delete_async(GLib.PRIORITY_DEFAULT, null); -export const fexist = (...xs) => fcheck(...xs).catch(noop); -export const fread = x => x.load_contents_async(null); - -export async function access(method, url, param, session = new Soup.Session()) { - let msg = param ? Soup.Message.new_from_encoded_form(method, url, Soup.form_encode_hash(param)) : Soup.Message.new(method, url); - let byt = await session.send_and_read_async(msg, GLib.PRIORITY_DEFAULT, null); - if(msg.statusCode !== Soup.Status.OK) raise(`Unexpected response: ${msg.get_reason_phrase()}`); - return decode(byt.get_data()); -} - -export async function execute(cmd) { - let proc = new Gio.Subprocess({ - argv: GLib.shell_parse_argv(cmd).at(1), - flags: Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE, - }); - proc.init(null); - let [stdout, stderr] = await proc.communicate_utf8_async(null, null); - let status = proc.get_exit_status(); - if(status) throw gerror(Gio.io_error_from_errno(status), stderr.trimEnd() || GLib.strerror(status)); - return stdout.trimEnd(); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/COPYING b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/COPYING deleted file mode 100644 index 8d61b15..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/COPYING +++ /dev/null @@ -1,341 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. - - - 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - - , 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 Library General -Public License instead of this License. - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/README.md b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/README.md deleted file mode 100644 index 53a8e81..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/README.md +++ /dev/null @@ -1,194 +0,0 @@ -

- -

-
- -![](media/design/png/dtp-main-p2.png) - -### Introduction - -Dash to Panel is an icon taskbar for Gnome Shell. This extension moves the dash into the gnome main panel so that the application launchers and system tray are combined into a single panel, similar to that found in KDE Plasma and Windows 7+. A separate dock is no longer needed for easy access to running and favorited applications. - -Beyond that, just about every aspect of the panel is fully customizable. From positioning and scaling panel elements to running indicators to multi-monitor display, to window previews and even intellihide, Dash to Panel has everything you need to make your workspace feel like home. - -### Features - -|Customizable appearance| -|:-----:| -|![screenshot](media/design/gif/customizable.gif)| -|Hide & show panel elements and set their positions, sizes & colors| - -## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Customizable running indicators
MetroCiliora/Dashes
CilioraSquares/Segmented
DashesDots/Solid
Set position, style, weight & color of running indicators to easily and quickly identify focused and unfocused applications
- -## - -|Live Previews on Hover| -|:-----:| -|![screenshot](media/design/gif/previews.gif)| -|Hover over the launcher icon for an open application to get a live window preview| - -## -|Launch by Number| -|:-----:| -|![](media/design/png/indicators-num.png.png)| -|Optionally launch your favorite applications via keyboard| - -## - -|Panel Intellihide| -|:-----:| -|![Intellihide](media/design/gif/Intellihide.gif)| -|Hide and reveal the panel according to your set preferences| - -## -|Additional Features|Feature Implemented| -|:-----|:-----:| -|Add "Show Desktop" button to panel|![](media/design/png/done.png)| -|Isolate running apps by workspaces and/or monitors|![](media/design/png/done.png)| -|Custom click behaviors (launch new window, cycle open windows, minimize, etc)|![](media/design/png/done.png)| -|Integrate native Gnome appMenu into right-click secondary menu|![](media/design/png/done.png)| -|Multi-monitor support|![](media/design/png/done.png)| -|Dynamic transparency|![](media/design/png/done.png)| -|Ungroup application windows|![](media/design/png/done.png)| -|Export and import settings|![](media/design/png/done.png)| -## - -### Installation - -**To install the most recent official release: -[Visit Dash-to-Panel at GNOME Extensions](https://extensions.gnome.org/extension/1160/dash-to-panel/)** - -To install a development version from source, please see the [Installation wiki page](https://github.com/home-sweet-gnome/dash-to-panel/wiki/Installation). - -## -### FAQ - -How do I customize the panel? [See the Wiki](https://github.com/home-sweet-gnome/dash-to-panel/wiki/Enable-and-Customize#customize-it) - -How do I embed my bottom left notification drawer into the panel like a system tray? [Top Icons Plus](https://extensions.gnome.org/extension/2311/topicons-plus) or [(K)StatusNotifierItem/AppIndicator Support](https://extensions.gnome.org/extension/615/appindicator-support) - -How do I add a traditional start menu? [Arc Menu](https://extensions.gnome.org/extension/3628/arcmenu/) - -How do I disable the hot corner? [No Topleft Hot Corner](https://extensions.gnome.org/extension/118/no-topleft-hot-corner) - -How do I move the notifications to somewhere other than the top center? [Notification Banner Reloaded](https://extensions.gnome.org/extension/4651/notification-banner-reloaded/) - -How do I display Minimize & Maximize buttons? In the Tweak Tool application, turn on `Windows > Titlebar Buttons > Minimize & Maximize`. - -How do I reset the extension to its default settings? `dconf reset -f /org/gnome/shell/extensions/dash-to-panel/`. - -## -### Themes -While this extension works well with most popular Gnome Shell themes, the following themes are known to have explicitly added custom styles for this extension: -- [Ciliora Tertia](https://github.com/zagortenay333/ciliora-tertia-shell) / [Ciliora Secunda](https://github.com/zagortenay333/ciliora-secunda-shell) -- [Plano](https://github.com/lassekongo83/plano-theme) - - -## -### Compatibility - -This extension has been tested with Gnome 3.18+. - -This extension manipulates the Gnome Main Panel, aka Top Bar. So, most other extensions which operate on the top bar should be compatible. - -## -### Volunteers needed! - -This extension could be even better with your help! Any items in the issue tracker labelled `help wanted` or `good first issue` are up for grabs. For more info, see the [Contributing wiki page](https://github.com/home-sweet-gnome/dash-to-panel/wiki/Contributing). - -## -### Credits - -This extension is developed and maintained by [@jderose9](https://github.com/jderose9) and [@charlesg99](https://github.com/charlesg99). - -Significant portions of code in this extension were derived from [Dash-to-Dock](https://micheleg.github.io/dash-to-dock/index.html). - -Additional credits: This extension leverages the work for [ZorinOS Taskbar](https://github.com/ZorinOS/zorin-taskbar) (used in [ZorinOS](https://zorinos.com/)) to show window previews and allow the dash from [Dash-to-Dock](https://micheleg.github.io/dash-to-dock/index.html) to be embedded in the Gnome main panel. -Code to set anchor position taken from [Thoma5/gnome-shell-extension-bottompanel](https://github.com/Thoma5/gnome-shell-extension-bottompanel). -Pattern for moving panel contents based on [Frippery Move Clock](http://frippery.org/extensions/) by R M Yorston. -Ideas for recursing child actors and assigning inline styles are based on code from the extension [StatusAreaHorizontalSpacing](https://bitbucket.org/mathematicalcoffee/status-area-horizontal-spacing-gnome-shell-extension). -## - -#### Thanks to the following people for contributing via pull requests: - -- @franglais125 for launching apps by number (w/ overlay), bug fixes, and issue support -- @LinxGem33 and @sbarrett322 for artwork, logos, screenshots and design effort -- @dziku1337 for peek mode in window previews -- @robrobinbin for configuring appMenu on/off in the panel -- @MartinPL for toggling favorites on/off in panel -- @jackwickham for thumbnail middle and right click actions -- @abakkk for centering the taskbar icons in the panel, and animated taskbar hovering -- @quasoft for changing of font weight of ungrouped application titles -- @jordanribera for using icon's dominant color as running indicator color -- @tper0700 for dynamically building context menu based on system capabilities -- @levacic for configurable minimized application title font color -- @l3nn4rt for toggling workspace switch popup -- @hlechner for adjustable show desktop line color and window preview icon size -- @ArtyomZorin for animated urgent icons -- @jvpessoa10 for additional click window cycle options -- @marksvc for assigning percent of display for panel length -- @philippun1 for GNOME 40 support :rocket: -- @HaselLoyance for toggle for notification counter badge -- @rastersoft for Desktop Icons NG integration - -#### Bug Fixes: -@imrvelj, @Teslator, @bil-elmoussaoui, @brandon-schumann, @sw9, @rockon999 , @lexruee, @3v1n0, @freeroot, @moqmar, @ArtyomZorin, @lkc0987, @saibotk, @vanillajonathan, @Zkdc, @leebickmtu, @l3nn4rt, @Melix19, @Aikatsui, @melix99, @kyrillzorin, @oneshadab, @CorvetteCole, @vantu5z, @spectreseven1138 - -#### Documentation Improvements: -@BoQsc, @zakkak, @dandv - -#### Translations: -@frnogueira / @victorwpbastos / @vagkaefer (pt_BR), @zeten30 (cs), @franglais125 / @calotam / @oeramirez (es), @LaurentTreguier / @SolarLiner (fr), @elsieholmes (uk), @hosiet (zh\_CN), @jonnius / @linuxr01 / @daPhipz (de), @urbalazs / @pappfer (hu), @crayxt (kk), @pkomur / @MartinPL / @alex4401 (pl), @AlexGluck / @GoodNike / @rjapolov / @vantu5z (ru), @sicklylife-jp / @ryonakano / @nexryai (ja), @oltulu / @TeknoMobil / @daenney (tr), @sbadux / @kowalski7cc / @l3nn4rt (it), @OriginCode / @pan93412 (zh\_TW), @ojn (sv), @frandieguez (gl), @kuroehanako / @MarongHappy (ko) - - -## -### License & Terms ![](media/design/png/copyleft-16.png) - -Dash to Panel is available under the terms of the GPL-v2 or later license See [`COPYING`](https://github.com/home-sweet-gnome/dash-to-panel/blob/master/COPYING) for details. - -![](https://img.shields.io/badge/Language-JavaScript-yellow.svg) ![](https://img.shields.io/badge/Licence-GPL--2.0-blue.svg) diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/appIcons.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/appIcons.js deleted file mode 100644 index d5f9c5e..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/appIcons.js +++ /dev/null @@ -1,1886 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * Some code was also adapted from the upstream Gnome Shell source code. - */ - - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; -import Graphene from 'gi://Graphene'; -import GObject from 'gi://GObject'; -import Mtk from 'gi://Mtk'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'; -import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js'; -import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'; -import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; -import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; -import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as Utils from './utils.js'; -import * as PanelSettings from './panelSettings.js'; -import * as Taskbar from './taskbar.js'; -import * as Progress from './progress.js'; -import {DTP_EXTENSION, SETTINGS, DESKTOPSETTINGS, EXTENSION_PATH} from './extension.js'; -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -//timeout names -const T2 = 'mouseScrollTimeout'; -const T3 = 'showDotsTimeout'; -const T4 = 'overviewWindowDragEndTimeout'; -const T5 = 'switchWorkspaceTimeout'; -const T6 = 'displayProperIndicatorTimeout'; - -//right padding defined for .overview-label in stylesheet.css -const TITLE_RIGHT_PADDING = 8; -const DOUBLE_CLICK_DELAY_MS = 450; - -let LABEL_GAP = 5; -let MAX_INDICATORS = 4; -export const DEFAULT_PADDING_SIZE = 4; - -let DOT_STYLE = { - DOTS: "DOTS", - SQUARES: "SQUARES", - DASHES: "DASHES", - SEGMENTED: "SEGMENTED", - CILIORA: "CILIORA", - METRO: "METRO", - SOLID: "SOLID" -} - -let DOT_POSITION = { - TOP: "TOP", - BOTTOM: "BOTTOM", - LEFT: 'LEFT', - RIGHT: 'RIGHT' -} - -let recentlyClickedAppLoopId = 0; -let recentlyClickedApp = null; -let recentlyClickedAppWindows = null; -let recentlyClickedAppIndex = 0; -let recentlyClickedAppMonitorIndex; - -let tracker = Shell.WindowTracker.get_default(); - -/** - * Extend AppIcon - * - * - Apply a css class based on the number of windows of each application (#N); - * - Draw a dot for each window of the application based on the default "dot" style which is hidden (#N); - * a class of the form "running#N" is applied to the AppWellIcon actor. - * like the original .running one. - * - add a .focused style to the focused app - * - Customize click actions. - * - Update minimization animation target - * - */ - -export const TaskbarAppIcon = GObject.registerClass({ -}, class TaskbarAppIcon extends AppDisplay.AppIcon { - - _init(appInfo, panel, iconParams, previewMenu, iconAnimator) { - this.dtpPanel = panel; - this._nWindows = 0; - this.window = appInfo.window; - this.isLauncher = appInfo.isLauncher; - this._previewMenu = previewMenu; - this.iconAnimator = iconAnimator; - this.lastClick = 0; - - super._init(appInfo.app, iconParams); - - this._timeoutsHandler = new Utils.TimeoutsHandler(); - - // Fix touchscreen issues before the listener is added by the parent constructor. - this._onTouchEvent = function(actor, event) { - if (event.type() == Clutter.EventType.TOUCH_BEGIN) { - // Open the popup menu on long press. - this._setPopupTimeout(); - } else if (this._menuTimeoutId != 0 && (event.type() == Clutter.EventType.TOUCH_END || event.type() == Clutter.EventType.TOUCH_CANCEL)) { - // Activate/launch the application. - this.activate(1); - this._removeMenuTimeout(); - } - // Disable dragging via touch screen as it's buggy as hell. Not perfect for tablet users, but the alternative is way worse. - // Also, EVENT_PROPAGATE launches applications twice with this solution, so this.activate(1) above must only be called if there's already a window. - return Clutter.EVENT_STOP; - }; - // Hack for missing TOUCH_END event. - this._onLeaveEvent = function(actor, event) { - this.fake_release(); - if (this._menuTimeoutId != 0) this.activate(1); // Activate/launch the application if TOUCH_END didn't fire. - this._removeMenuTimeout(); - }; - - - this._dot.set_width(0); - this._isGroupApps = SETTINGS.get_boolean('group-apps'); - - this._container = new St.Widget({ style_class: 'dtp-container', layout_manager: new Clutter.BinLayout() }); - this._dotsContainer = new St.Widget({ layout_manager: new Clutter.BinLayout() }); - this._dtpIconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(), style: getIconContainerStyle(panel.checkIfVertical()) }); - - this.remove_actor(this._iconContainer); - - this._dtpIconContainer.add_child(this._iconContainer); - - if (appInfo.window) { - let box = new St.BoxLayout(); - - this._windowTitle = new St.Label({ - y_align: Clutter.ActorAlign.CENTER, - x_align: Clutter.ActorAlign.START, - style_class: 'overview-label' - }); - - this._updateWindowTitle(); - this._updateWindowTitleStyle(); - - this._scaleFactorChangedId = Utils.getStageTheme().connect('changed', () => this._updateWindowTitleStyle()); - - box.add_child(this._dtpIconContainer); - box.add_child(this._windowTitle); - - this._dotsContainer.add_child(box); - } else { - this._dotsContainer.add_child(this._dtpIconContainer); - } - - this._container.add_child(this._dotsContainer); - this.set_child(this._container); - - if (panel.checkIfVertical()) { - this.set_width(panel.geom.w); - } - - // Monitor windows-changes instead of app state. - // Keep using the same Id and function callback (that is extended) - if(this._stateChangedId > 0) { - this.app.disconnect(this._stateChangedId); - this._stateChangedId = 0; - } - - this._onAnimateAppiconHoverChanged(); - this._setAppIconPadding(); - this._showDots(); - - this._focusWindowChangedId = global.display.connect('notify::focus-window', - this._onFocusAppChanged.bind(this)); - - this._windowEnteredMonitorId = this._windowLeftMonitorId = 0; - this._stateChangedId = this.app.connect('windows-changed', this.onWindowsChanged.bind(this)); - - if (!this.window) { - if (SETTINGS.get_boolean('isolate-monitors')) { - this._windowEnteredMonitorId = Utils.DisplayWrapper.getScreen().connect('window-entered-monitor', this.onWindowEnteredOrLeft.bind(this)); - this._windowLeftMonitorId = Utils.DisplayWrapper.getScreen().connect('window-left-monitor', this.onWindowEnteredOrLeft.bind(this)); - } - - this._titleWindowChangeId = 0; - this._minimizedWindowChangeId = 0; - } else { - this._titleWindowChangeId = this.window.connect('notify::title', - this._updateWindowTitle.bind(this)); - - this._minimizedWindowChangeId = this.window.connect('notify::minimized', - this._updateWindowTitleStyle.bind(this)); - } - - this._scrollEventId = this.connect('scroll-event', this._onMouseScroll.bind(this)); - - this._overviewWindowDragEndId = Main.overview.connect('window-drag-end', - this._onOverviewWindowDragEnd.bind(this)); - - this._switchWorkspaceId = global.window_manager.connect('switch-workspace', - this._onSwitchWorkspace.bind(this)); - - this._hoverChangeId = this.connect('notify::hover', () => this._onAppIconHoverChanged()); - - this._dtpSettingsSignalIds = [ - SETTINGS.connect('changed::animate-appicon-hover', this._onAnimateAppiconHoverChanged.bind(this)), - SETTINGS.connect('changed::dot-position', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-size', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-style-focused', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-style-unfocused', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-dominant', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-override', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-1', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-2', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-3', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-4', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-unfocused-different', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-unfocused-1', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-unfocused-2', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-unfocused-3', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::dot-color-unfocused-4', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::focus-highlight', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::focus-highlight-dominant', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::focus-highlight-color', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::focus-highlight-opacity', this._settingsChangeRefresh.bind(this)), - SETTINGS.connect('changed::group-apps-label-font-size', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-label-font-weight', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-label-font-color', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-label-font-color-minimized', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-label-max-width', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-use-fixed-width', this._updateWindowTitleStyle.bind(this)), - SETTINGS.connect('changed::group-apps-underline-unfocused', this._settingsChangeRefresh.bind(this)) - ] - - this._progressIndicator = new Progress.ProgressIndicator(this, panel.progressManager); - - this._numberOverlay(); - } - - getDragActor() { - return this.app.create_icon_texture(this.dtpPanel.taskbar.iconSize); - } - - // Used by TaskbarItemContainer to animate appIcons on hover - getCloneButton() { - // The source of the clone is this._container, - // using this.actor directly would break DnD style. - let clone = new Clutter.Clone({ - source: this.child, - x: this.child.x, y: this.child.y, - width: this.child.width, height: this.child.height, - pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), - opacity: 255, - reactive: false, - x_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER, - }); - - clone._delegate = this._delegate; - - // "clone" of this.actor - return new St.Button({ - child: clone, - x: this.x, y: this.y, - width: this.width, height: this.height, - reactive: false, - }); - } - - shouldShowTooltip() { - if (!SETTINGS.get_boolean('show-tooltip') || - (!this.isLauncher && SETTINGS.get_boolean("show-window-previews") && - this.getAppIconInterestingWindows().length > 0)) { - return false; - } else { - return this.hover && !this.window && - (!this._menu || !this._menu.isOpen) && - (this._previewMenu.getCurrentAppIcon() !== this); - } - } - - _onAppIconHoverChanged() { - if (!SETTINGS.get_boolean('show-window-previews') || - (!this.window && !this._nWindows)) { - return; - } - - if (this.hover) { - this._previewMenu.requestOpen(this); - } else { - this._previewMenu.requestClose(); - } - } - - _onDestroy() { - super._onDestroy(); - - this._timeoutsHandler.destroy(); - - this._previewMenu.close(true); - - // Disconect global signals - if (this._stateChangedId > 0) { - this.app.disconnect(this._stateChangedId); - this._stateChangedId = 0; - } - - if(this._overviewWindowDragEndId) - Main.overview.disconnect(this._overviewWindowDragEndId); - - if(this._focusWindowChangedId) - global.display.disconnect(this._focusWindowChangedId); - - if(this._titleWindowChangeId) - this.window.disconnect(this._titleWindowChangeId); - - if(this._minimizedWindowChangeId) - this.window.disconnect(this._minimizedWindowChangeId); - - if (this._windowEnteredMonitorId) { - Utils.DisplayWrapper.getScreen().disconnect(this._windowEnteredMonitorId); - Utils.DisplayWrapper.getScreen().disconnect(this._windowLeftMonitorId); - } - - if(this._switchWorkspaceId) - global.window_manager.disconnect(this._switchWorkspaceId); - - if(this._scaleFactorChangedId) - Utils.getStageTheme().disconnect(this._scaleFactorChangedId); - - if (this._hoverChangeId) { - this.disconnect(this._hoverChangeId); - } - - if (this._scrollEventId) { - this.disconnect(this._scrollEventId); - } - - for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) { - SETTINGS.disconnect(this._dtpSettingsSignalIds[i]); - } - } - - onWindowsChanged() { - this._updateWindows(); - this.updateIcon(); - - if (this._isGroupApps) - this._setIconStyle(); - } - - onWindowEnteredOrLeft(display, number, metaWindow) { - if (number > 0 && tracker.get_window_app(metaWindow) == this.app) { - this._updateWindows(); - this._displayProperIndicator(); - } - } - - updateTitleStyle() { - this._updateWindowTitleStyle(); - } - - // Update indicator and target for minimization animation - updateIcon() { - - // If (for unknown reason) the actor is not on the stage the reported size - // and position are random values, which might exceeds the integer range - // resulting in an error when assigned to the a rect. This is a more like - // a workaround to prevent flooding the system with errors. - if (this.get_stage() == null) - return; - - let rect = new Mtk.Rectangle(); - - [rect.x, rect.y] = this.get_transformed_position(); - [rect.width, rect.height] = this.get_transformed_size(); - - let windows = this.window ? [this.window] : this.getAppIconInterestingWindows(true); - windows.forEach(function(w) { - w.set_icon_geometry(rect); - }); - } - - _onAnimateAppiconHoverChanged() { - if (SETTINGS.get_boolean('animate-appicon-hover')) { - this._container.add_style_class_name('animate-appicon-hover'); - - // Workaround to prevent scaled icon from being ugly when it is animated on hover. - // It increases the "resolution" of the icon without changing the icon size. - this.icon.createIcon = (iconSize) => this.app.create_icon_texture(2 * iconSize); - this._iconIconBinActorAddedId = this.icon._iconBin.connect('actor-added', () => { - let size = this.icon.iconSize * Utils.getScaleFactor() - - if (this.icon._iconBin.child.mapped) { - this.icon._iconBin.child.set_size(size, size); - } else { - let iconMappedId = this.icon._iconBin.child.connect('notify::mapped', () => { - this.icon._iconBin.child.set_size(size, size); - this.icon._iconBin.child.disconnect(iconMappedId); - }); - } - }); - if (this.icon._iconBin.child) - this.icon._createIconTexture(this.icon.iconSize); - } else { - this._container.remove_style_class_name('animate-appicon-hover'); - - if (this._iconIconBinActorAddedId) { - this.icon._iconBin.disconnect(this._iconIconBinActorAddedId); - this._iconIconBinActorAddedId = 0; - this.icon.createIcon = this._createIcon.bind(this); - } - } - } - - _onMouseScroll(actor, event) { - let scrollAction = SETTINGS.get_string('scroll-icon-action'); - - if (scrollAction === 'PASS_THROUGH') { - return this.dtpPanel._onPanelMouseScroll(actor, event); - } else if (scrollAction === 'NOTHING' || (!this.window && !this._nWindows)) { - return; - } - - let direction = Utils.getMouseScrollDirection(event); - - if (direction && !this._timeoutsHandler.getId(T2)) { - this._timeoutsHandler.add([T2, SETTINGS.get_int('scroll-icon-delay'), () => {}]); - - let windows = this.getAppIconInterestingWindows(); - - windows.sort(Taskbar.sortWindowsCompareFunction); - Utils.activateSiblingWindow(windows, direction, this.window); - } - } - - _showDots() { - // Just update style if dots already exist - if (this._focusedDots && this._unfocusedDots) { - this._updateWindows(); - return; - } - - if (!this._isGroupApps) { - this._focusedDots = new St.Widget({ - layout_manager: new Clutter.BinLayout(), - x_expand: true, y_expand: true, - visible: false - }); - - let mappedId = this.connect('notify::mapped', () => { - this._displayProperIndicator(); - this.disconnect(mappedId); - }); - } else { - this._focusedDots = new St.DrawingArea(), - this._unfocusedDots = new St.DrawingArea(); - - this._focusedDots.connect('repaint', () => { - if (!this._dashItemContainer.animatingOut) - // don't draw and trigger more animations if the icon is in the middle of - // being removed from the panel - this._drawRunningIndicator(this._focusedDots, SETTINGS.get_string('dot-style-focused'), true); - }); - - this._unfocusedDots.connect('repaint', () => { - if (!this._dashItemContainer.animatingOut) - this._drawRunningIndicator(this._unfocusedDots, SETTINGS.get_string('dot-style-unfocused'), false); - }); - - this._dotsContainer.add_child(this._unfocusedDots); - - this._updateWindows(); - - this._timeoutsHandler.add([T3, 0, () => { - this._resetDots(); - this._displayProperIndicator(); - }]); - } - - this._dotsContainer.add_child(this._focusedDots); - } - - _resetDots() { - let position = SETTINGS.get_string('dot-position'); - let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; - let sizeProp = isHorizontalDots ? 'width' : 'height'; - let focusedDotStyle = SETTINGS.get_string('dot-style-focused'); - let unfocusedDotStyle = SETTINGS.get_string('dot-style-unfocused'); - - this._focusedIsWide = this._isWideDotStyle(focusedDotStyle); - this._unfocusedIsWide = this._isWideDotStyle(unfocusedDotStyle); - - [, this._containerSize] = this._container[`get_preferred_${sizeProp}`](-1); - - [this._focusedDots, this._unfocusedDots].forEach(d => { - d.set_size(-1, -1); - d.x_expand = d.y_expand = false; - - d[sizeProp] = 1; - d[(isHorizontalDots ? 'y' : 'x') + '_expand'] = true; - }); - } - - _settingsChangeRefresh() { - if (this._isGroupApps) { - this._updateWindows(); - this._resetDots(); - this._focusedDots.queue_repaint(); - this._unfocusedDots.queue_repaint(); - } - - this._displayProperIndicator(); - } - - _updateWindowTitleStyle() { - if (this._windowTitle) { - let useFixedWidth = SETTINGS.get_boolean('group-apps-use-fixed-width'); - let fontWeight = SETTINGS.get_string('group-apps-label-font-weight'); - let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor'); - let fontColor = this.window.minimized ? - SETTINGS.get_string('group-apps-label-font-color-minimized') : - SETTINGS.get_string('group-apps-label-font-color'); - let scaleFactor = Utils.getScaleFactor(); - let maxLabelWidth = SETTINGS.get_int('group-apps-label-max-width') * scaleFactor; - let variableWidth = !useFixedWidth || this.dtpPanel.checkIfVertical() || this.dtpPanel.taskbar.fullScrollView; - - this._windowTitle[(maxLabelWidth > 0 ? 'show' : 'hide')](); - this._windowTitle.set_width(variableWidth ? -1 : maxLabelWidth + TITLE_RIGHT_PADDING * scaleFactor); - - this._windowTitle.clutter_text.natural_width = useFixedWidth ? maxLabelWidth : 0; - this._windowTitle.clutter_text.natural_width_set = useFixedWidth; - - this._windowTitle.set_style('font-size: ' + SETTINGS.get_int('group-apps-label-font-size') * fontScale + 'px;' + - 'font-weight: ' + fontWeight + ';' + - (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') + - 'color: ' + fontColor); - } - } - - _updateWindowTitle() { - if (this._windowTitle.text != this.window.title) { - this._windowTitle.text = (this.window.title ? this.window.title : this.app.get_name()).replace(/\r?\n|\r/g, '').trim(); - - if (this._focusedDots) { - this._displayProperIndicator(); - } - } - } - - _setIconStyle(isFocused) { - let inlineStyle = 'margin: 0;'; - - if(SETTINGS.get_boolean('focus-highlight') && - this._checkIfFocusedApp() && !this.isLauncher && - (!this.window || isFocused) && !this._isThemeProvidingIndicator() && this._checkIfMonitorHasFocus()) { - let focusedDotStyle = SETTINGS.get_string('dot-style-focused'); - let pos = SETTINGS.get_string('dot-position'); - let highlightMargin = this._focusedIsWide ? SETTINGS.get_int('dot-size') : 0; - - if(!this.window) { - let containerWidth = this._dtpIconContainer.get_width() / Utils.getScaleFactor(); - let backgroundSize = containerWidth + "px " + - (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;"; - - if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED) - highlightMargin += 1; - - if (this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) { - let bgSvg = '/img/highlight_stacked_bg'; - - if (pos == DOT_POSITION.LEFT || pos == DOT_POSITION.RIGHT) { - bgSvg += (this.dtpPanel.checkIfVertical() ? '_2' : '_3'); - } - - inlineStyle += "background-image: url('" + EXTENSION_PATH + bgSvg + ".svg');" + - "background-position: 0 " + (pos == DOT_POSITION.TOP ? highlightMargin : 0) + "px;" + - "background-size: " + backgroundSize; - } - } - - let highlightColor = this._getFocusHighlightColor(); - inlineStyle += "background-color: " + cssHexTocssRgba(highlightColor, SETTINGS.get_int('focus-highlight-opacity') * 0.01); - } - - if(this._dotsContainer.get_style() != inlineStyle) { - this._dotsContainer.set_style(inlineStyle); - } - } - - _checkIfFocusedApp() { - return tracker.focus_app == this.app; - } - - _checkIfMonitorHasFocus() { - return global.display.focus_window && - (!SETTINGS.get_boolean('multi-monitors') || // only check same monitor index if multi window is enabled. - !SETTINGS.get_boolean('isolate-monitors') || - global.display.focus_window.get_monitor() === this.dtpPanel.monitor.index); - } - - _setAppIconPadding() { - let padding = getIconPadding(this.dtpPanel.monitor.index); - let margin = SETTINGS.get_int('appicon-margin'); - - this.set_style('padding:' + (this.dtpPanel.checkIfVertical() ? margin + 'px 0' : '0 ' + margin + 'px;')); - this._iconContainer.set_style('padding: ' + padding + 'px;'); - } - - popupMenu() { - this._removeMenuTimeout(); - this.fake_release(); - - if (!this._menu) { - this._menu = new TaskbarSecondaryMenu(this, this.dtpPanel.geom.position); - this._menu.setApp(this.app); - this._menu.connect('open-state-changed', (menu, isPoppedUp) => { - if (!isPoppedUp) - this._onMenuPoppedDown(); - else - this._previewMenu.close(true); - }); - let id = Main.overview.connect('hiding', () => { - this._menu.close(); - }); - this.connect('destroy', () => { - Main.overview.disconnect(id); - }); - - // We want to keep the item hovered while the menu is up - this._menu.blockSourceEvents = true; - - Main.uiGroup.add_actor(this._menu.actor); - this._menuManager.addMenu(this._menu); - } - this._menu.updateQuitText(); - - this.emit('menu-state-changed', true); - - this.set_hover(true); - this._menu.open(BoxPointer.PopupAnimation.FULL); - this._menuManager.ignoreRelease(); - this.emit('sync-tooltip'); - - return false; - } - - _onFocusAppChanged(windowTracker) { - this._displayProperIndicator(); - } - - _onOverviewWindowDragEnd(windowTracker) { - this._timeoutsHandler.add([T4, 0, () => { - if (SETTINGS.get_boolean('isolate-workspaces')) - this._updateWindows() - - this._displayProperIndicator() - }]); - } - - _onSwitchWorkspace(windowTracker) { - if (this._isGroupApps) { - this._timeoutsHandler.add([T5, 0, () => this._displayProperIndicator()]); - } else { - this._displayProperIndicator(); - } - } - - _displayProperIndicator() { - let isFocused = this._isFocusedWindow(); - let position = SETTINGS.get_string('dot-position'); - let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; - - this._setIconStyle(isFocused); - - if(!this._isGroupApps) { - if (this.window && (SETTINGS.get_boolean('group-apps-underline-unfocused') || isFocused)) { - let align = Clutter.ActorAlign[position == DOT_POSITION.TOP || position == DOT_POSITION.LEFT ? 'START' : 'END']; - - this._focusedDots.set_size(0, 0); - this._focusedDots[isHorizontalDots ? 'height' : 'width'] = this._getRunningIndicatorSize(); - - this._focusedDots.y_align = this._focusedDots.x_align = Clutter.ActorAlign.FILL; - this._focusedDots[(isHorizontalDots ? 'y' : 'x') + '_align'] = align; - this._focusedDots.background_color = this._getRunningIndicatorColor(isFocused); - this._focusedDots.show(); - } else if (this._focusedDots.visible) { - this._focusedDots.hide(); - } - } else { - let sizeProp = isHorizontalDots ? 'width' : 'height'; - let newFocusedDotsSize = 0; - let newFocusedDotsOpacity = 0; - let newUnfocusedDotsSize = 0; - let newUnfocusedDotsOpacity = 0; - - isFocused = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus(); - - this._timeoutsHandler.add([T6, 0, () => { - if(isFocused) - this.add_style_class_name('focused'); - else - this.remove_style_class_name('focused'); - }]); - - if(this._focusedIsWide) { - newFocusedDotsSize = (isFocused && this._nWindows > 0) ? this._containerSize : 0; - newFocusedDotsOpacity = 255; - } else { - newFocusedDotsSize = this._containerSize; - newFocusedDotsOpacity = (isFocused && this._nWindows > 0) ? 255 : 0; - } - - if(this._unfocusedIsWide) { - newUnfocusedDotsSize = (!isFocused && this._nWindows > 0) ? this._containerSize : 0; - newUnfocusedDotsOpacity = 255; - } else { - newUnfocusedDotsSize = this._containerSize; - newUnfocusedDotsOpacity = (!isFocused && this._nWindows > 0) ? 255 : 0; - } - - // Only animate if... - // animation is enabled in settings - // AND (going from a wide style to a narrow style indicator or vice-versa - // OR going from an open app to a closed app or vice versa) - let animate = SETTINGS.get_boolean('animate-app-switch') && - ((this._focusedIsWide != this._unfocusedIsWide) || - (this._focusedDots[sizeProp] != newUnfocusedDotsSize || this._unfocusedDots[sizeProp] != newFocusedDotsSize)) - let duration = animate ? Taskbar.DASH_ANIMATION_TIME : 0.001; - - this._animateDotDisplay(this._focusedDots, newFocusedDotsSize, this._unfocusedDots, newUnfocusedDotsOpacity, sizeProp, duration); - this._animateDotDisplay(this._unfocusedDots, newUnfocusedDotsSize, this._focusedDots, newFocusedDotsOpacity, sizeProp, duration); - } - } - - _animateDotDisplay(dots, newSize, otherDots, newOtherOpacity, sizeProp, duration) { - Utils.stopAnimations(dots) - - let tweenOpts = { - time: duration, - transition: 'easeInOutCubic', - onComplete: () => { - if(newOtherOpacity > 0) - otherDots.opacity = newOtherOpacity; - } - }; - - if(newOtherOpacity == 0) - otherDots.opacity = newOtherOpacity; - - tweenOpts[sizeProp] = newSize; - - Utils.animate(dots, tweenOpts); - } - - _isFocusedWindow() { - let focusedWindow = global.display.focus_window; - - while (focusedWindow) { - if (focusedWindow == this.window) { - return true; - } - - focusedWindow = focusedWindow.get_transient_for(); - } - - return false; - } - - _isWideDotStyle(dotStyle) { - return dotStyle == DOT_STYLE.SEGMENTED || - dotStyle == DOT_STYLE.CILIORA || - dotStyle == DOT_STYLE.METRO || - dotStyle == DOT_STYLE.SOLID; - } - - _isThemeProvidingIndicator() { - // This is an attempt to determine if the theme is providing their own - // running indicator by way of a border image on the icon, for example in - // the theme Ciliora - return (this.icon.get_stage() && - this.icon.get_theme_node().get_border_image()); - } - - activate(button, modifiers, handleAsGrouped) { - let event = Clutter.get_current_event(); - - modifiers = event ? event.get_state() : modifiers || 0; - - // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.) - modifiers = modifiers & (Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK); - - let ctrlPressed = modifiers & Clutter.ModifierType.CONTROL_MASK - - if (ctrlPressed) { - // CTRL-click or hotkey with ctrl - return this._launchNewInstance(true); - } - - // We check what type of click we have and if the modifier SHIFT is - // being used. We then define what buttonAction should be for this - // event. - let buttonAction = 0; - let doubleClick; - - if (button && button == 2 ) { - if (modifiers & Clutter.ModifierType.SHIFT_MASK) - buttonAction = SETTINGS.get_string('shift-middle-click-action'); - else - buttonAction = SETTINGS.get_string('middle-click-action'); - } - else if (button && button == 1) { - let now = global.get_current_time() - - doubleClick = now - this.lastClick < DOUBLE_CLICK_DELAY_MS - this.lastClick = now - - if (modifiers & Clutter.ModifierType.SHIFT_MASK) - buttonAction = SETTINGS.get_string('shift-click-action'); - else - buttonAction = SETTINGS.get_string('click-action'); - } - - let closePreview = () => this._previewMenu.close(SETTINGS.get_boolean('window-preview-hide-immediate-click')); - let appCount = this.getAppIconInterestingWindows().length; - let previewedAppIcon = this._previewMenu.getCurrentAppIcon(); - - if (this.window || buttonAction != 'TOGGLE-SHOWPREVIEW') - closePreview() - - // We check if the app is running, and that the # of windows is > 0 in - // case we use workspace isolation, - let appIsRunning = this.app.state == Shell.AppState.RUNNING && appCount > 0; - - // We customize the action only when the application is already running - if (appIsRunning && !this.isLauncher) { - if (this.window && !handleAsGrouped) { - //ungrouped applications behaviors - switch (buttonAction) { - case 'RAISE': case 'CYCLE': case 'CYCLE-MIN': case 'MINIMIZE': case 'TOGGLE-SHOWPREVIEW': case 'TOGGLE-CYCLE': - if (!Main.overview._shown && - (buttonAction == 'MINIMIZE' || buttonAction == 'TOGGLE-SHOWPREVIEW' || buttonAction == 'TOGGLE-CYCLE' || buttonAction == 'CYCLE-MIN') && - (this._isFocusedWindow() || (buttonAction == 'MINIMIZE' && (button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK)))) { - this.window.minimize(); - } else { - Main.activateWindow(this.window); - } - - break; - - case "LAUNCH": - this._launchNewInstance(); - break; - - case "QUIT": - this.window.delete(global.get_current_time()); - break; - } - } else { - //grouped application behaviors - let monitor = this.dtpPanel.monitor; - let appHasFocus = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus(); - - switch (buttonAction) { - case "RAISE": - activateAllWindows(this.app, monitor); - break; - - case "LAUNCH": - this._launchNewInstance(); - break; - - case "MINIMIZE": - // In overview just activate the app, unless the acion is explicitely - // requested with a keyboard modifier - if (!Main.overview._shown || modifiers){ - // If we have button=2 or a modifier, allow minimization even if - // the app is not focused - if (appHasFocus || button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK) { - // minimize all windows on double click and always in the case of primary click without - // additional modifiers - let all_windows = (button == 1 && ! modifiers) || doubleClick; - minimizeWindow(this.app, all_windows, monitor); - } - else - activateAllWindows(this.app, monitor); - } - else - this.app.activate(); - break; - - case "CYCLE": - if (!Main.overview._shown){ - if (appHasFocus) - cycleThroughWindows(this.app, false, false, monitor); - else { - activateFirstWindow(this.app, monitor); - } - } - else - this.app.activate(); - break; - case "CYCLE-MIN": - if (!Main.overview._shown){ - if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE")) - cycleThroughWindows(this.app, false, true, monitor); - else { - activateFirstWindow(this.app, monitor); - } - } - else - this.app.activate(); - break; - case "TOGGLE-SHOWPREVIEW": - if (!Main.overview._shown) { - if (appCount == 1) { - closePreview() - - if (appHasFocus) - minimizeWindow(this.app, false, monitor); - else - activateFirstWindow(this.app, monitor); - } else { - if (doubleClick) { - // minimize all windows if double clicked - closePreview() - minimizeWindow(this.app, true, monitor); - } else if (previewedAppIcon != this) { - this._previewMenu.open(this); - } - - this.emit('sync-tooltip'); - } - } - else - this.app.activate(); - break; - case "TOGGLE-CYCLE": - if (!Main.overview._shown) { - if (appCount == 1) { - if (appHasFocus) - minimizeWindow(this.app, false, monitor); - else - activateFirstWindow(this.app, monitor); - } else { - cycleThroughWindows(this.app, false, false, monitor); - } - } - else - this.app.activate(); - break; - case "QUIT": - closeAllWindows(this.app, monitor); - break; - } - } - } - else { - this._launchNewInstance(); - } - - global.display.emit('grab-op-begin', null, null); - Main.overview.hide(); - } - - _launchNewInstance(ctrlPressed) { - let maybeAnimate = () => SETTINGS.get_boolean('animate-window-launch') && this.animateLaunch() - - if ((ctrlPressed || this.app.state == Shell.AppState.RUNNING) && - this.app.can_open_new_window()) { - maybeAnimate(); - this.app.open_new_window(-1); - } else { - let windows = this.window ? [this.window] : this.app.get_windows(); - - if (windows.length) { - Main.activateWindow(windows[0]); - } else { - maybeAnimate(); - this.app.activate(); - } - } - } - - _updateWindows() { - let windows = [this.window]; - - if (!this.window) { - windows = this.getAppIconInterestingWindows(); - - this._nWindows = windows.length; - - for (let i = 1; i <= MAX_INDICATORS; i++){ - let className = 'running'+i; - if(i != this._nWindows) - this.remove_style_class_name(className); - else - this.add_style_class_name(className); - } - } - - this._previewMenu.update(this, windows); - } - - _getRunningIndicatorCount() { - return Math.min(this._nWindows, MAX_INDICATORS); - } - - _getRunningIndicatorSize() { - return SETTINGS.get_int('dot-size') * Utils.getScaleFactor(); - } - - _getRunningIndicatorColor(isFocused) { - let color; - const fallbackColor = new Clutter.Color({ red: 82, green: 148, blue: 226, alpha: 255 }); - - if (SETTINGS.get_boolean('dot-color-dominant')) { - let dce = new Utils.DominantColorExtractor(this.app); - let palette = dce._getColorPalette(); - if (palette) { - color = Clutter.color_from_string(palette.original)[1]; - } else { // unable to determine color, fall back to theme - let themeNode = this._dot.get_theme_node(); - color = themeNode.get_background_color(); - - // theme didn't provide one, use a default - if(color.alpha == 0) color = fallbackColor; - } - } else if(SETTINGS.get_boolean('dot-color-override')) { - let dotColorSettingPrefix = 'dot-color-'; - - if(!isFocused && SETTINGS.get_boolean('dot-color-unfocused-different')) - dotColorSettingPrefix = 'dot-color-unfocused-'; - - color = Clutter.color_from_string(SETTINGS.get_string(dotColorSettingPrefix + (this._getRunningIndicatorCount() || 1) ))[1]; - } else { - // Re-use the style - background color, and border width and color - - // of the default dot - let themeNode = this._dot.get_theme_node(); - color = themeNode.get_background_color(); - - // theme didn't provide one, use a default - if(color.alpha == 0) color = fallbackColor; - } - - return color; - } - - _getFocusHighlightColor() { - if (SETTINGS.get_boolean('focus-highlight-dominant')) { - let dce = new Utils.DominantColorExtractor(this.app); - let palette = dce._getColorPalette(); - if (palette) return palette.original; - } - return SETTINGS.get_string('focus-highlight-color'); - } - - _drawRunningIndicator(area, type, isFocused) { - let n = this._getRunningIndicatorCount(); - - if (!n) { - return; - } - - let position = SETTINGS.get_string('dot-position'); - let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; - let bodyColor = this._getRunningIndicatorColor(isFocused); - let [areaWidth, areaHeight] = area.get_surface_size(); - let cr = area.get_context(); - let size = this._getRunningIndicatorSize(); - - let areaSize = areaWidth; - let startX = 0; - let startY = 0; - - if (isHorizontalDots) { - if (position == DOT_POSITION.BOTTOM) { - startY = areaHeight - size; - } - } else { - areaSize = areaHeight; - - if (position == DOT_POSITION.RIGHT) { - startX = areaWidth - size; - } - } - - if (type == DOT_STYLE.SOLID || type == DOT_STYLE.METRO) { - if (type == DOT_STYLE.SOLID || n <= 1) { - cr.translate(startX, startY); - Clutter.cairo_set_source_color(cr, bodyColor); - cr.newSubPath(); - cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [areaSize, size] : [size, areaSize])); - cr.fill(); - } else { - let blackenedLength = (1 / 48) * areaSize; // need to scale with the SVG for the stacked highlight - let darkenedLength = isFocused ? (2 / 48) * areaSize : (10 / 48) * areaSize; - let blackenedColor = bodyColor.shade(.3); - let darkenedColor = bodyColor.shade(.7); - let solidDarkLength = areaSize - darkenedLength; - let solidLength = solidDarkLength - blackenedLength; - - cr.translate(startX, startY); - - Clutter.cairo_set_source_color(cr, bodyColor); - cr.newSubPath(); - cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [solidLength, size] : [size, solidLength])); - cr.fill(); - Clutter.cairo_set_source_color(cr, blackenedColor); - cr.newSubPath(); - cr.rectangle.apply(cr, isHorizontalDots ? [solidLength, 0, 1, size] : [0, solidLength, size, 1]); - cr.fill(); - Clutter.cairo_set_source_color(cr, darkenedColor); - cr.newSubPath(); - cr.rectangle.apply(cr, isHorizontalDots ? [solidDarkLength, 0, darkenedLength, size] : [0, solidDarkLength, size, darkenedLength]); - cr.fill(); - } - } else { - let spacing = Math.ceil(areaSize / 18); // separation between the indicators - let length; - let dist; - let indicatorSize; - let translate; - let preDraw = () => {}; - let draw; - let drawDash = (i, dashLength) => { - dist = i * dashLength + i * spacing; - cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0, dashLength, size] : [0, dist, size, dashLength])); - }; - - switch (type) { - case DOT_STYLE.CILIORA: - spacing = size; - length = areaSize - (size * (n - 1)) - (spacing * (n - 1)); - translate = () => cr.translate(startX, startY); - preDraw = () => { - cr.newSubPath(); - cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [length, size] : [size, length])); - }; - draw = i => { - dist = length + (i * spacing) + ((i - 1) * size); - cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size])); - }; - break; - case DOT_STYLE.DOTS: - let radius = size / 2; - - translate = () => { - indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2); - cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); - } - draw = i => { - dist = (2 * i + 1) * radius + i * spacing; - cr.arc.apply(cr, (isHorizontalDots ? [dist, radius] : [radius, dist]).concat([radius, 0, 2 * Math.PI])); - }; - break; - case DOT_STYLE.SQUARES: - translate = () => { - indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2); - cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); - } - draw = i => { - dist = i * size + i * spacing; - cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size])); - }; - break; - case DOT_STYLE.DASHES: - length = Math.floor(areaSize / 4) - spacing; - translate = () => { - indicatorSize = Math.floor((areaSize - n * length - (n - 1) * spacing) / 2); - cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); - } - draw = i => drawDash(i, length); - break; - case DOT_STYLE.SEGMENTED: - length = Math.ceil((areaSize - ((n - 1) * spacing)) / n); - translate = () => cr.translate(startX, startY); - draw = i => drawDash(i, length); - break; - } - - translate(); - - Clutter.cairo_set_source_color(cr, bodyColor); - preDraw(); - for (let i = 0; i < n; i++) { - cr.newSubPath(); - draw(i); - } - cr.fill(); - } - - cr.$dispose(); - } - - _numberOverlay() { - // Add label for a Hot-Key visual aid - this._numberOverlayLabel = new St.Label({ style_class: 'badge' }); - this._numberOverlayBin = new St.Bin({ - child: this._numberOverlayLabel, y: 2 - }); - this._numberOverlayLabel.add_style_class_name('number-overlay'); - this._numberOverlayOrder = -1; - this._numberOverlayBin.hide(); - - this._dtpIconContainer.add_child(this._numberOverlayBin); - } - - updateHotkeyNumberOverlay() { - this.updateNumberOverlay(this._numberOverlayBin, true); - } - - updateNumberOverlay(bin, fixedSize) { - // We apply an overall scale factor that might come from a HiDPI monitor. - // Clutter dimensions are in physical pixels, but CSS measures are in logical - // pixels, so make sure to consider the scale. - // Set the font size to something smaller than the whole icon so it is - // still visible. The border radius is large to make the shape circular - let [minWidth, natWidth] = this._dtpIconContainer.get_preferred_width(-1); - let font_size = Math.round(Math.max(12, 0.3 * natWidth) / Utils.getScaleFactor()); - let size = Math.round(font_size * 1.3); - let label = bin.child; - let style = 'font-size: ' + font_size + 'px;' + - 'border-radius: ' + this.icon.iconSize + 'px;' + - 'height: ' + size +'px;'; - - if (fixedSize || label.get_text().length == 1) { - style += 'width: ' + size + 'px;'; - } else { - style += 'padding: 0 2px;'; - } - - bin.x = 2; - label.set_style(style); - } - - setNumberOverlay(number) { - this._numberOverlayOrder = number; - this._numberOverlayLabel.set_text(number.toString()); - } - - toggleNumberOverlay(activate) { - if (activate && this._numberOverlayOrder > -1) - this._numberOverlayBin.show(); - else - this._numberOverlayBin.hide(); - } - - handleDragOver(source, actor, x, y, time) { - if (source == Main.xdndHandler) { - this._previewMenu.close(true); - } - - return DND.DragMotionResult.CONTINUE; - } - - getAppIconInterestingWindows(isolateMonitors) { - return getInterestingWindows(this.app, this.dtpPanel.monitor, isolateMonitors); - } -}); -TaskbarAppIcon.prototype.scaleAndFade = TaskbarAppIcon.prototype.undoScaleAndFade = () => {}; - -export function minimizeWindow(app, param, monitor){ - // Param true make all app windows minimize - let windows = getInterestingWindows(app, monitor); - let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - for (let i = 0; i < windows.length; i++) { - let w = windows[i]; - if (w.get_workspace() == current_workspace && w.showing_on_its_workspace()){ - w.minimize(); - // Just minimize one window. By specification it should be the - // focused window on the current workspace. - if(!param) - break; - } - } -} - -/* - * By default only non minimized windows are activated. - * This activates all windows in the current workspace. - */ -export function activateAllWindows(app, monitor){ - - // First activate first window so workspace is switched if needed, - // then activate all other app windows in the current workspace. - let windows = getInterestingWindows(app, monitor); - let w = windows[0]; - Main.activateWindow(w); - let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace_index(); - - if (windows.length <= 0) - return; - - for (let i = windows.length - 1; i >= 0; i--){ - if (windows[i].get_workspace().index() == activeWorkspace){ - Main.activateWindow(windows[i]); - } - } -} - -export function activateFirstWindow(app, monitor){ - - let windows = getInterestingWindows(app, monitor); - Main.activateWindow(windows[0]); -} - -export function cycleThroughWindows(app, reversed, shouldMinimize, monitor) { - // Store for a little amount of time last clicked app and its windows - // since the order changes upon window interaction - let MEMORY_TIME=3000; - - let app_windows = getInterestingWindows(app, monitor); - - if(shouldMinimize) - app_windows.push("MINIMIZE"); - - if (recentlyClickedAppLoopId > 0) - GLib.Source.remove(recentlyClickedAppLoopId); - - recentlyClickedAppLoopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, - MEMORY_TIME, resetRecentlyClickedApp); - - // If there isn't already a list of windows for the current app, - // or the stored list is outdated, use the current windows list. - if (!recentlyClickedApp || - recentlyClickedApp.get_id() != app.get_id() || - recentlyClickedAppWindows.length != app_windows.length || - recentlyClickedAppMonitorIndex != monitor.index) { - recentlyClickedApp = app; - recentlyClickedAppWindows = app_windows; - recentlyClickedAppIndex = 0; - recentlyClickedAppMonitorIndex = monitor.index; - } - - if (reversed) { - recentlyClickedAppIndex--; - if (recentlyClickedAppIndex < 0) recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1; - } else { - recentlyClickedAppIndex++; - } - let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; - - if(recentlyClickedAppWindows[index] === "MINIMIZE") - minimizeWindow(app, true, monitor); - else - Main.activateWindow(recentlyClickedAppWindows[index]); -} - -export function resetRecentlyClickedApp() { - if (recentlyClickedAppLoopId > 0) - GLib.Source.remove(recentlyClickedAppLoopId); - - recentlyClickedAppLoopId=0; - recentlyClickedApp =null; - recentlyClickedAppWindows = null; - recentlyClickedAppIndex = 0; - recentlyClickedAppMonitorIndex = null; - - return false; -} - -export function closeAllWindows(app, monitor) { - let windows = getInterestingWindows(app, monitor); - for (let i = 0; i < windows.length; i++) - windows[i].delete(global.get_current_time()); -} - -// Filter out unnecessary windows, for instance -// nautilus desktop window. -export function getInterestingWindows(app, monitor, isolateMonitors) { - let windows = ( - app ? - app.get_windows() : - global.get_window_actors().map(wa => wa.get_meta_window()) - ).filter(w => !w.skip_taskbar); - - // When using workspace or monitor isolation, we filter out windows - // that are not in the current workspace or on the same monitor as the appicon - if (SETTINGS.get_boolean('isolate-workspaces')) - windows = windows.filter(function(w) { - return w.get_workspace() && - w.get_workspace() == Utils.getCurrentWorkspace(); - }); - - if (monitor && SETTINGS.get_boolean('multi-monitors') && (isolateMonitors || SETTINGS.get_boolean('isolate-monitors'))) { - windows = windows.filter(function(w) { - return w.get_monitor() == monitor.index; - }); - } - - return windows; -} - -export function cssHexTocssRgba(cssHex, opacity) { - let bigint = parseInt(cssHex.slice(1), 16); - let r = (bigint >> 16) & 255; - let g = (bigint >> 8) & 255; - let b = bigint & 255; - - return 'rgba(' + [r, g, b].join(',') + ',' + opacity + ')'; -} - -export function getIconPadding(monitorIndex) { - let panelSize = PanelSettings.getPanelSize(SETTINGS, monitorIndex); - let padding = SETTINGS.get_int('appicon-padding'); - let availSize = panelSize - Taskbar.MIN_ICON_SIZE - panelSize % 2; - - if (padding * 2 > availSize) { - padding = availSize * .5; - } - - return padding; -} - -/** - * Extend AppMenu (AppIconMenu for pre gnome 41) - * - * - hide 'Show Details' according to setting - * - show windows header only if show-window-previews is disabled - * - Add close windows option based on quitfromdash extension - * (https://github.com/deuill/shell-extension-quitfromdash) - */ - -export class TaskbarSecondaryMenu extends AppMenu.AppMenu { - - constructor(source, side) { - super(source, side); - // constructor parameter does nos work for some reason - this._enableFavorites = true; - this._showSingleWindows = true; - - // Remove "Show Details" menu item - if(!SETTINGS.get_boolean('secondarymenu-contains-showdetails')) { - let existingMenuItems = this._getMenuItems(); - for (let i = 0; i < existingMenuItems.length; i++) { - let item = existingMenuItems[i]; - if (item !== undefined && item.label !== undefined) { - if (item.label.text == "Show Details") { - this.box.remove_child(item.actor); - } - } - } - } - - // replace quit item - delete this._quitItem; - this._quitItem = this.addAction(_('Quit'), () => this._quitFromTaskbar()); - } - - updateQuitText() { - let count = this.sourceActor.window ? 1 : - getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor).length; - - if ( count > 0) { - let quitFromTaskbarMenuText = ""; - if (count == 1) - quitFromTaskbarMenuText = _("Quit"); - else - quitFromTaskbarMenuText = _("Quit") + ' ' + count + ' ' + _("Windows"); - - this._quitItem.label.set_text(quitFromTaskbarMenuText); - } - } - - _quitFromTaskbar() { - let time = global.get_current_time() - let windows = - this.sourceActor.window ? // ungrouped applications - [this.sourceActor.window] : - getInterestingWindows(this._app, this.sourceActor.dtpPanel.monitor) - - if (windows.length == this._app.get_windows().length) - this._app.request_quit() - - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - windows.forEach((w) => !!w.get_compositor_private() && w.delete(time++)); - - return GLib.SOURCE_REMOVE; - }); - } -} - -/** - * This function is used for extendDashItemContainer - */ -export function ItemShowLabel() { - if (!this._labelText) - return; - - this.label.set_text(this._labelText); - this.label.opacity = 0; - this.label.show(); - - let [stageX, stageY] = this.get_transformed_position(); - let node = this.label.get_theme_node(); - - let itemWidth = this.allocation.x2 - this.allocation.x1; - let itemHeight = this.allocation.y2 - this.allocation.y1; - - let labelWidth = this.label.get_width(); - let labelHeight = this.label.get_height(); - - let position = this._dtpPanel.getPosition(); - let labelOffset = node.get_length('-x-offset'); - - // From TaskbarItemContainer - if (this._getIconAnimationOffset) - labelOffset += this._getIconAnimationOffset(); - - let xOffset = Math.floor((itemWidth - labelWidth) / 2); - let x = stageX + xOffset - let y = stageY + (itemHeight - labelHeight) * .5; - - switch(position) { - case St.Side.TOP: - y = stageY + labelOffset + itemHeight; - break; - case St.Side.BOTTOM: - y = stageY - labelHeight - labelOffset; - break; - case St.Side.LEFT: - x = stageX + labelOffset + itemWidth; - break; - case St.Side.RIGHT: - x = stageX - labelWidth - labelOffset; - break; - } - - // keep the label inside the screen border - // Only needed for the x coordinate. - - // Leave a few pixel gap - let gap = LABEL_GAP; - let monitor = Main.layoutManager.findMonitorForActor(this); - if ( x - monitor.x < gap) - x += monitor.x - x + labelOffset; - else if ( x + labelWidth > monitor.x + monitor.width - gap) - x -= x + labelWidth -( monitor.x + monitor.width) + gap; - - this.label.set_position(Math.round(x), Math.round(y)); - - let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME; - - if (duration > 1) { - duration /= 1000; - } - - Utils.animate(this.label, { - opacity: 255, - time: duration, - transition: 'easeOutQuad', - }); -} - -/** - * A wrapper class around the ShowAppsIcon class. - * - * - Pass settings to the constructor - * - set label position based on dash orientation (Note, I am reusing most machinery of the appIcon class) - * - implement a popupMenu based on the AppIcon code (Note, I am reusing most machinery of the appIcon class) - * - * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. - * thus use this pattern where the real showAppsIcon object is encaptulated, and a reference to it will be properly wired upon - * use of this class in place of the original showAppsButton. - * - */ -export const ShowAppsIconWrapper = class extends EventEmitter { - - constructor(dtpPanel) { - super(); - - this.realShowAppsIcon = new Dash.ShowAppsIcon(); - - /* the variable equivalent to toggleButton has a different name in the appIcon class - (actor): duplicate reference to easily reuse appIcon methods */ - this.actor = this.realShowAppsIcon.toggleButton; - this.realShowAppsIcon.show(false); - - // Re-use appIcon methods - this._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout; - this._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout; - this._onKeyboardPopupMenu = AppDisplay.AppIcon.prototype._onKeyboardPopupMenu; - - // No action on clicked (showing of the appsview is controlled elsewhere) - this._onClicked = (actor, button) => this._removeMenuTimeout(); - - this.actor.connect('leave-event', this._onLeaveEvent.bind(this)); - this.actor.connect('button-press-event', this._onButtonPress.bind(this)); - this.actor.connect('touch-event', this._onTouchEvent.bind(this)); - this.actor.connect('clicked', this._onClicked.bind(this)); - this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this)); - - this._menu = null; - this._menuManager = new PopupMenu.PopupMenuManager(this.actor); - this._menuTimeoutId = 0; - - this.realShowAppsIcon._dtpPanel = dtpPanel; - Taskbar.extendDashItemContainer(this.realShowAppsIcon); - - let customIconPath = SETTINGS.get_string('show-apps-icon-file'); - - this.realShowAppsIcon.icon.createIcon = function(size) { - this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic', - icon_size: size, - style_class: 'show-apps-icon', - track_hover: true }); - - if (customIconPath) { - this._iconActor.gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(customIconPath) }); - } - - return this._iconActor; - }; - - this._changedShowAppsIconId = SETTINGS.connect('changed::show-apps-icon-file', () => { - customIconPath = SETTINGS.get_string('show-apps-icon-file'); - this.realShowAppsIcon.icon._createIconTexture(this.realShowAppsIcon.icon.iconSize); - }); - - this._changedAppIconPaddingId = SETTINGS.connect('changed::appicon-padding', () => this.setShowAppsPadding()); - this._changedAppIconSidePaddingId = SETTINGS.connect('changed::show-apps-icon-side-padding', () => this.setShowAppsPadding()); - - this.setShowAppsPadding(); - } - - _onButtonPress(_actor, event) { - let button = event.get_button(); - if (button == 1) { - this._setPopupTimeout(); - } else if (button == 3) { - this.popupMenu(); - return Clutter.EVENT_STOP; - } - return Clutter.EVENT_PROPAGATE; - } - - _onLeaveEvent(_actor, _event) { - this.actor.fake_release(); - this._removeMenuTimeout(); - } - - _onTouchEvent(actor, event) { - if (event.type() == Clutter.EventType.TOUCH_BEGIN) - this._setPopupTimeout(); - - return Clutter.EVENT_PROPAGATE; - } - - _onMenuPoppedDown() { - this._menu.sourceActor = this.actor; - this.actor.sync_hover(); - this.emit('menu-state-changed', false); - } - - setShowAppsPadding() { - let padding = getIconPadding(this.realShowAppsIcon._dtpPanel.monitor.index); - let sidePadding = SETTINGS.get_int('show-apps-icon-side-padding'); - let isVertical = this.realShowAppsIcon._dtpPanel.checkIfVertical(); - - this.actor.set_style('padding:' + (padding + (isVertical ? sidePadding : 0)) + 'px ' + (padding + (isVertical ? 0 : sidePadding)) + 'px;'); - } - - createMenu() { - if (!this._menu) { - this._menu = new MyShowAppsIconMenu(this.realShowAppsIcon, this.realShowAppsIcon._dtpPanel); - this._menu.connect('open-state-changed', (menu, isPoppedUp) => { - if (!isPoppedUp) - this._onMenuPoppedDown(); - }); - let id = Main.overview.connect('hiding', () => { - this._menu.close(); - }); - this._menu.actor.connect('destroy', () => { - Main.overview.disconnect(id); - }); - - // We want to keep the item hovered while the menu is up - this._menu.blockSourceEvents = true; - - Main.uiGroup.add_actor(this._menu.actor); - this._menuManager.addMenu(this._menu); - } - } - - popupMenu(sourceActor = null) { - this._removeMenuTimeout(); - this.actor.fake_release(); - this.createMenu(); - - this._menu.updateItems(sourceActor == null ? this.realShowAppsIcon : sourceActor); - - this.actor.set_hover(true); - this._menu.open(BoxPointer.PopupAnimation.FULL); - this._menuManager.ignoreRelease(); - this.emit('sync-tooltip'); - - return false; - } - - shouldShowTooltip() { - return SETTINGS.get_boolean('show-tooltip') && - (this.actor.hover && (!this._menu || !this._menu.isOpen)); - } - - destroy() { - SETTINGS.disconnect(this._changedShowAppsIconId); - SETTINGS.disconnect(this._changedAppIconSidePaddingId); - SETTINGS.disconnect(this._changedAppIconPaddingId); - - this.realShowAppsIcon.destroy(); - } -}; - -/** - * A menu for the showAppsIcon - */ -export const MyShowAppsIconMenu = class extends PopupMenu.PopupMenu { - - constructor(actor, dtpPanel) { - super(actor, 0, dtpPanel.getPosition()); - - this._dtpPanel = dtpPanel; - - this.updateItems(actor); - } - - updateItems(sourceActor) { - this.sourceActor = sourceActor; - - this.removeAll(); - - if (this.sourceActor != Main.layoutManager.dummyCursor) { - this._appendItem({ - title: _('Power options'), - cmd: ['gnome-control-center', 'power'] - }); - - this._appendItem({ - title: _('Event logs'), - cmd: ['gnome-logs'] - }); - - this._appendItem({ - title: _('System'), - cmd: ['gnome-control-center', 'info-overview'] - }); - - this._appendItem({ - title: _('Device Management'), - cmd: ['gnome-control-center', 'display'] - }); - - this._appendItem({ - title: _('Disk Management'), - cmd: ['gnome-disks'] - }); - - this._appendList( - SETTINGS.get_strv('show-apps-button-context-menu-commands'), - SETTINGS.get_strv('show-apps-button-context-menu-titles') - ) - - this._appendSeparator(); - } - - this._appendItem({ - title: _('Terminal'), - cmd: ['gnome-terminal'] - }); - - this._appendItem({ - title: _('System monitor'), - cmd: ['gnome-system-monitor'] - }); - - this._appendItem({ - title: _('Files'), - cmd: ['nautilus'] - }); - - this._appendItem({ - title: _('Extensions'), - cmd: ['gnome-shell-extension-prefs'] - }); - - this._appendItem({ - title: _('Settings'), - cmd: ['gnome-control-center'] - }); - - this._appendList( - SETTINGS.get_strv('panel-context-menu-commands'), - SETTINGS.get_strv('panel-context-menu-titles') - ) - - this._appendSeparator(); - - let lockTaskbarMenuItem = this._appendMenuItem(SETTINGS.get_boolean('taskbar-locked') ? _('Unlock taskbar') : _('Lock taskbar')); - lockTaskbarMenuItem.connect('activate', () => { - SETTINGS.set_boolean('taskbar-locked', !SETTINGS.get_boolean('taskbar-locked')); - }); - - let settingsMenuItem = this._appendMenuItem(_('Dash to Panel Settings')); - settingsMenuItem.connect('activate', () => DTP_EXTENSION.openPreferences()) - - if(this.sourceActor == Main.layoutManager.dummyCursor) { - this._appendSeparator(); - let item = this._appendMenuItem(this._dtpPanel._restoreWindowList ? _('Restore Windows') : _('Show Desktop')); - item.connect('activate', this._dtpPanel._onShowDesktopButtonPress.bind(this._dtpPanel)); - } - } - - - // Only add menu entries for commands that exist in path - _appendItem(info) { - if (GLib.find_program_in_path(info.cmd[0])) { - let item = this._appendMenuItem(_(info.title)); - - item.connect('activate', function() { - print("activated: " + info.title); - Util.spawn(info.cmd); - }); - return item; - } - - return null; - } - - _appendList(commandList, titleList) { - if (commandList.length != titleList.length) { - return; - } - - for (let entry = 0; entry < commandList.length; entry++) { - _appendItem({ - title: titleList[entry], - cmd: commandList[entry].split(' ') - }); - } - } - - _appendSeparator() { - let separator = new PopupMenu.PopupSeparatorMenuItem(); - this.addMenuItem(separator); - } - - _appendMenuItem(labelText) { - // FIXME: app-well-menu-item style - let item = new PopupMenu.PopupMenuItem(labelText); - this.addMenuItem(item); - return item; - } -}; - - -export const getIconContainerStyle = function(isVertical) { - let style = 'padding: '; - - if (SETTINGS.get_boolean('group-apps')) { - style += (isVertical ? '0;' : '0 ' + DEFAULT_PADDING_SIZE + 'px;'); - } else { - style += (isVertical ? '' : '0 ') + DEFAULT_PADDING_SIZE + 'px;'; - } - - return style; -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/desktopIconsIntegration.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/desktopIconsIntegration.js deleted file mode 100644 index 9a93d07..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/desktopIconsIntegration.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - * The code in this file is distributed under a "1-clause BSD license", - * which makes it compatible with GPLv2 and GPLv3 too, and others. - * - * License text: - * - * Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com) - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 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 OR CONTRIBUTORS 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. - */ - -/******************************************************************************* - * Integration class - * - * This class must be added to other extensions in order to integrate - * them with Desktop Icons NG. It allows an extension to notify how much margin - * it uses in each side of each monitor. - * - * DON'T SEND PATCHES TO THIS FILE TO THE EXTENSION MAINTAINER. SEND THEM TO - * DESKTOP ICONS NG MAINTAINER: https://gitlab.com/rastersoft/desktop-icons-ng - * - * In the *enable()* function, create a *DesktopIconsUsableAreaClass()* - * object with - * - * new DesktopIconsIntegration.DesktopIconsUsableAreaClass(object); - * - * Now, in the *disable()* function just call to the *destroy()* method before - * nullifying the pointer. You must create a new object in enable() the next - * time the extension is enabled. - * - * In your code, every time you change the margins, you should call first to - * *resetMargins()* method to clear the current margins, and then call to - * *setMargins(...)* method as many times as you need to set the margins in each - * monitor. You don't need to call it for all the monitors, only for those where - * you are painting something. If you don't set values for a monitor, they will - * be considered zero. - * - * The margins values are relative to the monitor border. - * - *******************************************************************************/ - -import GLib from 'gi://GLib'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import {EXTENSION_UUID} from './extension.js'; - -import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'; - -const IDENTIFIER_UUID = "130cbc66-235c-4bd6-8571-98d2d8bba5e2"; - -export const DesktopIconsUsableAreaClass = class { - constructor() { - this._extensionManager = Main.extensionManager; - this._timedMarginsID = 0; - this._margins = {}; - this._emID = this._extensionManager.connect('extension-state-changed', (_obj, extension) => { - if (!extension) - return; - - // If an extension is being enabled and lacks the DesktopIconsUsableArea object, we can avoid launching a refresh - if (extension.state === ExtensionUtils.ExtensionState.ENABLED) { - this._sendMarginsToExtension(extension); - return; - } - // if the extension is being disabled, we must do a full refresh, because if there were other extensions originally - // loaded after that extension, those extensions will be disabled and enabled again without notification - this._changedMargins(); - }); - } - - /** - * Sets or updates the top, bottom, left and right margins for a - * monitor. Values are measured from the monitor border (and NOT from - * the workspace border). - * - * @param {int} monitor Monitor number to which set the margins. - * A negative value means "the primary monitor". - * @param {int} top Top margin in pixels - * @param {int} bottom Bottom margin in pixels - * @param {int} left Left margin in pixels - * @param {int} right Right margin in pixels - */ - setMargins(monitor, top, bottom, left, right) { - this._margins[monitor] = { - 'top': top, - 'bottom': bottom, - 'left': left, - 'right': right - }; - this._changedMargins(); - } - - /** - * Clears the current margins. Must be called before configuring the monitors - * margins with setMargins(). - */ - resetMargins() { - this._margins = {}; - this._changedMargins(); - } - - /** - * Disconnects all the signals and removes the margins. - */ - destroy() { - if (this._emID) { - this._extensionManager.disconnect(this._emID); - this._emID = 0; - } - if (this._timedMarginsID) { - GLib.source_remove(this._timedMarginsID); - this._timedMarginsID = 0; - } - this._margins = null; - this._changedMargins(); - } - - _changedMargins() { - if (this._timedMarginsID) { - GLib.source_remove(this._timedMarginsID); - } - this._timedMarginsID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, ()=> { - this._sendMarginsToAll(); - this._timedMarginsID = 0; - return GLib.SOURCE_REMOVE; - }); - } - - _sendMarginsToAll() { - this._extensionManager.getUuids().forEach(uuid => - this._sendMarginsToExtension(this._extensionManager.lookup(uuid))); - } - - _sendMarginsToExtension(extension) { - // check that the extension is an extension that has the logic to accept - // working margins - if (extension?.state !== ExtensionUtils.ExtensionState.ENABLED) - return; - - const usableArea = extension?.stateObj?.DesktopIconsUsableArea; - if (usableArea?.uuid === IDENTIFIER_UUID) - usableArea.setMarginsForExtension(EXTENSION_UUID, this._margins); - } -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/extension.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/extension.js deleted file mode 100644 index dc9c246..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/extension.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Dash-To-Panel extension for Gnome 3 - * Copyright 2016 Jason DeRose (jderose9) and Charles Gagnon (charlesg99) - * - * 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 . - * - */ - - -import Gio from 'gi://Gio'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; -import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as PanelManager from './panelManager.js'; -import * as Utils from './utils.js'; -import * as AppIcons from './appIcons.js'; - - -const UBUNTU_DOCK_UUID = 'ubuntu-dock@ubuntu.com'; - -let panelManager; -let extensionChangedHandler; -let startupCompleteHandler; -let disabledUbuntuDock; -let extensionSystem = Main.extensionManager; - -export let DTP_EXTENSION = null; -export let SETTINGS = null; -export let DESKTOPSETTINGS = null; -export let PERSISTENTSTORAGE = null; -export let EXTENSION_UUID = null; -export let EXTENSION_PATH = null; - -export default class DashToPanelExtension extends Extension { - constructor(metadata) { - super(metadata); - console.log(`Initiating ${this.uuid}`); - - this._realHasOverview = Main.sessionMode.hasOverview; - - //create an object that persists until gnome-shell is restarted, even if the extension is disabled - PERSISTENTSTORAGE = {}; - } - - enable() { - DTP_EXTENSION = this; - - // The Ubuntu Dock extension might get enabled after this extension - extensionChangedHandler = extensionSystem.connect('extension-state-changed', (data, extension) => { - if (extension.uuid === UBUNTU_DOCK_UUID && extension.state === 1) { - _enable(this); - } - }); - - //create a global object that can emit signals and conveniently expose functionalities to other extensions - global.dashToPanel = new EventEmitter(); - - _enable(this); - } - - disable(reset = false) { - panelManager.disable(); - - DTP_EXTENSION = null; - SETTINGS = null; - DESKTOPSETTINGS = null; - panelManager = null; - - if (!reset) { - extensionSystem.disconnect(extensionChangedHandler); - delete global.dashToPanel; - - // Re-enable Ubuntu Dock if it was disabled by dash to panel - if (disabledUbuntuDock && Main.sessionMode.allowExtensions) { - (extensionSystem._callExtensionEnable || extensionSystem.enableExtension).call(extensionSystem, UBUNTU_DOCK_UUID); - } - - AppIcons.resetRecentlyClickedApp(); - } - - if (startupCompleteHandler) { - Main.layoutManager.disconnect(startupCompleteHandler); - startupCompleteHandler = null; - } - - Main.sessionMode.hasOverview = this._realHasOverview; - } -} - -function _enable(extension) { - let ubuntuDock = Main.extensionManager.lookup(UBUNTU_DOCK_UUID); - - if (ubuntuDock && ubuntuDock.stateObj && ubuntuDock.stateObj.dockManager) { - // Disable Ubuntu Dock - let extensionOrder = (extensionSystem.extensionOrder || extensionSystem._extensionOrder); - - Utils.getStageTheme().get_theme().unload_stylesheet(ubuntuDock.stylesheet); - ubuntuDock.stateObj.disable(); - disabledUbuntuDock = true; - ubuntuDock.state = 2; //ExtensionState.DISABLED - extensionOrder.splice(extensionOrder.indexOf(UBUNTU_DOCK_UUID), 1); - - //reset to prevent conflicts with the ubuntu-dock - if (panelManager) { - extension.disable(true); - } - } - - if (panelManager) return; //already initialized - - SETTINGS = extension.getSettings('org.gnome.shell.extensions.dash-to-panel'); - DESKTOPSETTINGS = new Gio.Settings({schema_id: 'org.gnome.desktop.interface'}); - EXTENSION_UUID = extension.uuid - EXTENSION_PATH = extension.path - - Main.layoutManager.startInOverview = !SETTINGS.get_boolean('hide-overview-on-startup'); - - if (SETTINGS.get_boolean('hide-overview-on-startup') && Main.layoutManager._startingUp) { - Main.sessionMode.hasOverview = false; - startupCompleteHandler = Main.layoutManager.connect('startup-complete', () => { - Main.sessionMode.hasOverview = extension._realHasOverview - }); - } - - panelManager = new PanelManager.PanelManager(); - - panelManager.enable(); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg.svg b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg.svg deleted file mode 100644 index 977146b..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_2.svg b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_2.svg deleted file mode 100644 index 47aa802..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_2.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_3.svg b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_3.svg deleted file mode 100644 index 80420fd..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/img/highlight_stacked_bg_3.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/intellihide.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/intellihide.js deleted file mode 100644 index e47171f..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/intellihide.js +++ /dev/null @@ -1,426 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -import Clutter from 'gi://Clutter'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as GrabHelper from 'resource:///org/gnome/shell/ui/grabHelper.js'; -import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js'; -import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js'; - -import * as Proximity from './proximity.js'; -import * as Utils from './utils.js'; -import {SETTINGS} from './extension.js'; - -//timeout intervals -const CHECK_POINTER_MS = 200; -const CHECK_GRAB_MS = 400; -const POST_ANIMATE_MS = 50; -const MIN_UPDATE_MS = 250; - -//timeout names -const T1 = 'checkGrabTimeout'; -const T2 = 'limitUpdateTimeout'; -const T3 = 'postAnimateTimeout'; -const T4 = 'panelBoxClipTimeout'; - -const SIDE_CONTROLS_ANIMATION_TIME = OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (OverviewControls.SIDE_CONTROLS_ANIMATION_TIME > 1 ? 1000 : 1); - -export const Hold = { - NONE: 0, - TEMPORARY: 1, - PERMANENT: 2 -}; - -export const Intellihide = class { - - constructor(dtpPanel) { - this._dtpPanel = dtpPanel; - this._panelBox = dtpPanel.panelBox; - this._panelManager = dtpPanel.panelManager; - this._proximityManager = this._panelManager.proximityManager; - this._holdStatus = Hold.NONE; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._timeoutsHandler = new Utils.TimeoutsHandler(); - - this._intellihideChangedId = SETTINGS.connect('changed::intellihide', () => this._changeEnabledStatus()); - this._intellihideOnlySecondaryChangedId = SETTINGS.connect('changed::intellihide-only-secondary', () => this._changeEnabledStatus()); - - this.enabled = false; - this._changeEnabledStatus(); - } - - enable() { - this.enabled = true; - this._monitor = this._dtpPanel.monitor; - this._animationDestination = -1; - this._pendingUpdate = false; - this._hoveredOut = false; - this._windowOverlap = false; - this._translationProp = 'translation_' + (this._dtpPanel.checkIfVertical() ? 'x' : 'y'); - - this._panelBox.translation_y = 0; - this._panelBox.translation_x = 0; - - this._setTrackPanel(true); - this._bindGeneralSignals(); - - if (SETTINGS.get_boolean('intellihide-hide-from-windows')) { - this._proximityWatchId = this._proximityManager.createWatch( - this._panelBox.get_parent(), - this._dtpPanel.monitor.index, - Proximity.Mode[SETTINGS.get_string('intellihide-behaviour')], - 0, 0, - overlap => { - this._windowOverlap = overlap; - this._queueUpdatePanelPosition(); - } - ); - } - - this._setRevealMechanism(); - this._queueUpdatePanelPosition(); - } - - disable(reset) { - if (this._proximityWatchId) { - this._proximityManager.removeWatch(this._proximityWatchId); - } - - this._setTrackPanel(false); - - this._signalsHandler.destroy(); - this._timeoutsHandler.destroy(); - - this._removeRevealMechanism(); - - this._revealPanel(!reset); - - this.enabled = false; - } - - destroy() { - SETTINGS.disconnect(this._intellihideChangedId); - SETTINGS.disconnect(this._intellihideOnlySecondaryChangedId); - - if (this.enabled) { - this.disable(); - } - } - - toggle() { - this[this._holdStatus & Hold.PERMANENT ? 'release' : 'revealAndHold'](Hold.PERMANENT); - } - - revealAndHold(holdStatus) { - if (this.enabled && !this._holdStatus) { - this._revealPanel(); - } - - this._holdStatus |= holdStatus; - } - - release(holdStatus) { - this._holdStatus -= holdStatus; - - if (this.enabled && !this._holdStatus) { - this._queueUpdatePanelPosition(); - } - } - - reset() { - this.disable(true); - this.enable(); - } - - _changeEnabledStatus() { - let intellihide = SETTINGS.get_boolean('intellihide'); - let onlySecondary = SETTINGS.get_boolean('intellihide-only-secondary'); - let enabled = intellihide && !(this._dtpPanel.isPrimary && onlySecondary); - - if (this.enabled !== enabled) { - this[enabled ? 'enable' : 'disable'](); - } - } - - _bindGeneralSignals() { - this._signalsHandler.add( - [ - this._dtpPanel.taskbar, - ['menu-closed', 'end-drag'], - () => { - this._panelBox.sync_hover(); - this._onHoverChanged(); - } - ], - [ - SETTINGS, - [ - 'changed::intellihide-use-pressure', - 'changed::intellihide-hide-from-windows', - 'changed::intellihide-behaviour', - 'changed::intellihide-pressure-threshold', - 'changed::intellihide-pressure-time' - ], - () => this.reset() - ], - [ - this._panelBox, - 'notify::hover', - () => this._onHoverChanged() - ], - [ - this._dtpPanel.taskbar.previewMenu, - 'open-state-changed', - () => this._queueUpdatePanelPosition() - ], - [ - Main.overview, - [ - 'showing', - 'hiding' - ], - () => this._queueUpdatePanelPosition() - ] - ); - - if (Meta.is_wayland_compositor()) { - this._signalsHandler.add([ - this._panelBox, - 'notify::visible', - () => Utils.setDisplayUnredirect(!this._panelBox.visible) - ]); - } - } - - _onHoverChanged() { - this._hoveredOut = !this._panelBox.hover; - this._queueUpdatePanelPosition(); - } - - _setTrackPanel(enable) { - let actorData = Utils.getTrackedActorData(this._panelBox) - - actorData.affectsStruts = !enable; - actorData.trackFullscreen = !enable; - - this._panelBox.track_hover = enable; - this._panelBox.reactive = enable; - this._panelBox.visible = enable ? enable : this._panelBox.visible; - - Main.layoutManager._queueUpdateRegions(); - } - - _setRevealMechanism() { - if (global.display.supports_extended_barriers() && SETTINGS.get_boolean('intellihide-use-pressure')) { - this._edgeBarrier = this._createBarrier(); - this._pressureBarrier = new Layout.PressureBarrier( - SETTINGS.get_int('intellihide-pressure-threshold'), - SETTINGS.get_int('intellihide-pressure-time'), - Shell.ActionMode.NORMAL - ); - this._pressureBarrier.addBarrier(this._edgeBarrier); - this._signalsHandler.add([this._pressureBarrier, 'trigger', () => this._queueUpdatePanelPosition(true)]); - } else { - this._pointerWatch = PointerWatcher.getPointerWatcher() - .addWatch(CHECK_POINTER_MS, (x, y) => this._checkMousePointer(x, y)); - } - } - - _removeRevealMechanism() { - if (this._pointerWatch) { - PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch); - } - - if (this._pressureBarrier) { - this._pressureBarrier.destroy(); - this._edgeBarrier.destroy(); - - this._pressureBarrier = 0; - } - } - - _createBarrier() { - let position = this._dtpPanel.geom.position; - let opts = { display: global.display }; - - if (this._dtpPanel.checkIfVertical()) { - opts.y1 = this._monitor.y; - opts.y2 = this._monitor.y + this._monitor.height; - opts.x1 = opts.x2 = this._monitor.x; - } else { - opts.x1 = this._monitor.x; - opts.x2 = this._monitor.x + this._monitor.width; - opts.y1 = opts.y2 = this._monitor.y; - } - - if (position == St.Side.TOP) { - opts.directions = Meta.BarrierDirection.POSITIVE_Y; - } else if (position == St.Side.BOTTOM) { - opts.y1 = opts.y2 = opts.y1 + this._monitor.height; - opts.directions = Meta.BarrierDirection.NEGATIVE_Y; - } else if (position == St.Side.LEFT) { - opts.directions = Meta.BarrierDirection.POSITIVE_X; - } else { - opts.x1 = opts.x2 = opts.x1 + this._monitor.width; - opts.directions = Meta.BarrierDirection.NEGATIVE_X; - } - - return new Meta.Barrier(opts); - } - - _checkMousePointer(x, y) { - let position = this._dtpPanel.geom.position; - - if (!this._panelBox.hover && !Main.overview.visible && - ((position == St.Side.TOP && y <= this._monitor.y + 1) || - (position == St.Side.BOTTOM && y >= this._monitor.y + this._monitor.height - 1) || - (position == St.Side.LEFT && x <= this._monitor.x + 1) || - (position == St.Side.RIGHT && x >= this._monitor.x + this._monitor.width - 1)) && - ((x >= this._monitor.x && x < this._monitor.x + this._monitor.width) && - (y >= this._monitor.y && y < this._monitor.y + this._monitor.height))) { - this._queueUpdatePanelPosition(true); - } - } - - _queueUpdatePanelPosition(fromRevealMechanism) { - if (!fromRevealMechanism && this._timeoutsHandler.getId(T2) && !Main.overview.visible) { - //unless this is a mouse interaction or entering/leaving the overview, limit the number - //of updates, but remember to update again when the limit timeout is reached - this._pendingUpdate = true; - } else if (!this._holdStatus) { - this._checkIfShouldBeVisible(fromRevealMechanism) ? this._revealPanel() : this._hidePanel(); - this._timeoutsHandler.add([T2, MIN_UPDATE_MS, () => this._endLimitUpdate()]); - } - } - - _endLimitUpdate() { - if (this._pendingUpdate) { - this._pendingUpdate = false; - this._queueUpdatePanelPosition(); - } - } - - _checkIfShouldBeVisible(fromRevealMechanism) { - if (Main.overview.visibleTarget || this._dtpPanel.taskbar.previewMenu.opened || - this._dtpPanel.taskbar._dragMonitor || this._panelBox.get_hover() || this._checkIfGrab()) { - return true; - } - - if (fromRevealMechanism) { - let mouseBtnIsPressed = global.get_pointer()[2] & Clutter.ModifierType.BUTTON1_MASK; - - //the user is trying to reveal the panel - if (this._monitor.inFullscreen && !mouseBtnIsPressed) { - return SETTINGS.get_boolean('intellihide-show-in-fullscreen'); - } - - return !mouseBtnIsPressed; - } - - if (!SETTINGS.get_boolean('intellihide-hide-from-windows')) { - return this._panelBox.hover; - } - - return !this._windowOverlap; - } - - _checkIfGrab() { - let isGrab - - if (GrabHelper._grabHelperStack) - // gnome-shell < 42 - isGrab = GrabHelper._grabHelperStack.some(gh => gh._owner == this._dtpPanel.panel) - else if (global.stage.get_grab_actor) { - // gnome-shell >= 42 - let grabActor = global.stage.get_grab_actor() - let sourceActor = grabActor?._sourceActor || grabActor - - isGrab = sourceActor && - (sourceActor == Main.layoutManager.dummyCursor || - this._dtpPanel.statusArea.quickSettings?.menu.actor.contains(sourceActor) || - this._dtpPanel.panel.contains(sourceActor)) - } - - if (isGrab) - //there currently is a grab on a child of the panel, check again soon to catch its release - this._timeoutsHandler.add([T1, CHECK_GRAB_MS, () => this._queueUpdatePanelPosition()]); - - return isGrab; - } - - _revealPanel(immediate) { - if (!this._panelBox.visible) { - this._panelBox.visible = true; - this._dtpPanel.taskbar._shownInitially = false; - } - - this._animatePanel(0, immediate); - } - - _hidePanel(immediate) { - let position = this._dtpPanel.geom.position; - let size = this._panelBox[position == St.Side.LEFT || position == St.Side.RIGHT ? 'width' : 'height']; - let coefficient = position == St.Side.TOP || position == St.Side.LEFT ? -1 : 1; - - this._animatePanel(size * coefficient, immediate); - } - - _animatePanel(destination, immediate) { - let animating = Utils.isAnimating(this._panelBox, this._translationProp); - - if (!((animating && destination === this._animationDestination) || - (!animating && destination === this._panelBox[this._translationProp]))) { - //the panel isn't already at, or animating to the asked destination - if (animating) { - Utils.stopAnimations(this._panelBox); - } - - this._animationDestination = destination; - - if (immediate) { - this._panelBox[this._translationProp] = destination; - this._panelBox.visible = !destination; - } else { - let tweenOpts = { - //when entering/leaving the overview, use its animation time instead of the one from the settings - time: Main.overview.visible ? - SIDE_CONTROLS_ANIMATION_TIME : - SETTINGS.get_int('intellihide-animation-time') * 0.001, - //only delay the animation when hiding the panel after the user hovered out - delay: destination != 0 && this._hoveredOut ? SETTINGS.get_int('intellihide-close-delay') * 0.001 : 0, - transition: 'easeOutQuad', - onComplete: () => { - this._panelBox.visible = !destination; - Main.layoutManager._queueUpdateRegions(); - this._timeoutsHandler.add([T3, POST_ANIMATE_MS, () => this._queueUpdatePanelPosition()]); - } - }; - - tweenOpts[this._translationProp] = destination; - Utils.animate(this._panelBox, tweenOpts); - } - } - - this._hoveredOut = false; - } -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/cs/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/cs/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 07395365f4c6812bbe81daf0142c3fc7a743db99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16769 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 F{2RuRvH1W1 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fa/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fa/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 82cc5c2888e8238d67f3e78ec8f34eab7774ef37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19898 zcmbuF36xw_na3}iKx9V{703h4&>?gu9l{opKnMwmBqU^EQA8?Tue-}sR~1#&Nt$H_ zLXz&$C@82XBZ?wfOlY$Z2r>ww;xO*GRCN@P@yr~@@tpAt9>?+Mncx53`T8(Kt(U?QQiQr*i2Y4Jf%|Fle zcqPa%bG651pypcv9t@T}_Iq6G@m7z2>+w#H>pc#7{IJK5f?DSuP%M7Jw?E|ZVgG)! zf4|i~KLH*~|0n(P3!wP=u7Cc4#~*oo(c@3S)9Cke@WL}>Y)0)1|9{TaI$M34+cC> z2c?(ygPQ*)k3HZxo(td+-~h-JW*vAmct5E59svVzH+UrY6W{(4D87CRjt9rR-Qn4w z=6Nrud2Rx=?*d3yGYE>02SLsEWpFY$44w(T4E_yxFoU$uiJ;cG5S#{H3%&!~Vbzk=fXkD&B$IL;J+XMyTJ-{TG72|SlTjk^ncH+UbYeLMlG z|G$Bfu^l%0=& zvb*2=_eTb9zEeTXcRq+onyW$0_aRX0-3v-yJ3xk-CqY;>BOsx}{0Y?fV=yl1Z6YW; zx(?L%TS4jflc41C2#5&HQ=s-Y0!seB0ws^%fRfjrL5+JWlSyxkv4<-YwkQ1cFf4}kZ8;`bbkO#IIV1MntL^WO;`0^S3PulvAG@BvWcz6Xl$S3&ic z(Vqhx3u@mpKuq4O0%Zq-;4R?8pzLxy%9;Z%2F2IC;ML#*;4<)cpvKR}=%lX?fc!I6 z{%BthfSUI?5EjfUpyoN0mxqE!c|0C`3(qHmvV+sW!@()O{X+1%gN(TZ)VTXm_F>@X zK-tHaK-t09eEUzpgLxkD_)Bm)&#!KLwaquQ^JE--JM)^m86Tlf@2RIvC1-64bz;nUAb1E?loDWK#>p}7Nd5>E__1o$3=intg{{@sBW+I$2I3K(S{2GW$n?HaW zcM6-+e6u`W0R}uT0a1au8N3vH5M+pX8C(dScph_tH-YN671aBmfyaX55E5H7@AP;j zcn#0DfwGSmLFw}y7dSs(3Q7*^KkTp$du+; zP=5a3p!%Q6rr!%*0%pJug8}#-pzQrN48T`G zjXMP8yd69dlpjn2PXXTxo(y(@lJ70x3E*Ae0`ODdiQp?BteDq8t#%3Q0>owi@{@GJgP%2QOLV?DcB! z2%fW`?7a_^9B=o}p97ELc?XC%?B_cE;;!Zg(D!YNF`ogif&LEqB=lV<`n-iNk3hqa zYzh`F?@xh8LQA2WAbrH^1JI#*@SlBP9{LG%j&FMqyaB30KlN>byHnrw^+(WF2sPS# zuf4tvlC4Ysr$VPg+H(M%0by$9Ht0K$KJSA55xP|m{_|C^9zCQ`y47a~^ifDMe-E?~ zl77AieGqy#q|dLQ8|^n|2S4-Q1@ez>=MGmsXu($p)W#h&>_%l=rHJ2=m}^J^iR+&&{A=?3Vt4X7So!w?aHkdF$e{)^MLWC84>9c>o z@l_0>({u)Fa)oShO;9X_g`lli4*Cl{@9C)PHVc^E5MUQe(?`=DaD0?gG-oMP^2B*0Nq0xIC<8a{0=P z$+=lUUs&i5a@DZU%&3$yg`kqVC7gL?r7x4upE+xJZ>|!Q%Eg{?rZ4C!_JtK@ul5GB zFI%>F;fm#R7hWG+wK%wT_R^)ZuUdY6$GBx-7*u=1U`8hBEr;DR&+M&MOO@%9C$Cwv zrlY6O-%%|0OwQ-J!a^miOfKfL?eRlTDc?S|V@gMFwU33bxN1dkMOX;SnS8LMeKk6!RoMF$rTI1)Bq9YGu5y>V{&Fz(9KiUZLDL)WbI{^ncY>*t)SNk~H)dtE<8R$=AQg=Oa;?+4($T)6SSS%m>wCurdtF;p#AxXRbB9 zxqKMp3PE>&K40l7hv>Jjm<<`XCc~7gbCul6JdcI0-eMWZ^}%+~TVyM_LQjw>m8|W+ zjenKT^wU@G3gMcB4ga=+65LxxBAblo*uIu%s=2-}XzQy?^b^{)ff5|}m4Zy%H{LH( z4Fp}inL-cZVux4&yC~$U#WIZ9x31M(7WQUV=a9E#z9^T?=EL?m@Ug0+@zt{4Tz7TS zs1C(yueq#bF1S^Yc{ns#S=2$*ZMy4xQ9S}Qh9DaT4>SDgXFEn<^AcKxk z?3{eD5_&DOyKK-KX0l;9C>1LhfI1WltHZTSX6E!)SRH%LqYU?e(OV4!Xs^h=SNa{M zUiZ0uc4?oj-aE@^8b8p5X;gdh^Pb*Vk#lUT3kMa`@Dxl6`f?}-j?CqmO0TxQ#2VeQ zuv*0;Dz-TkU_)|Wb9tE048RlW2!pVY!C$bP9Ky}#bG^B27+@2XYNlLuM$yop_v)P( zx3!z7OLdJi=6;0h_lDIMs+DM_%BpIy6nWR>xk^c_SXtmog+?QaUYGj|1;=4l#*2Na zYk#4;*u^?o`9osW(I7F{m%+)LpwVdb#)s7s{+PpCoZ^vBF(_bcEX3C;&;4cVDCY8k zLZ*+1vNF@PN&y&S@pcx!itH|Oj=2(Q==B$r!f=(Qomay7W=)(=dLXk z5x)#G*Jr<0B6a##qo2`xH(|xhU0X%oW?pVBZZXeGC^DUS#X{8?a!~BHI!wt94yt(! zrMXjNVGW`lyL%+r^nA(_L0f6<#IY9++OlDHraxZ|$ReHGQCUWs2DX}gO_=NHt!nDA z_LKCmmg{xzIlLlQo!`IGTv5(sa|n;nqIly4B^^ZiRZxk0$&hVOuxd(onJ*vGI2ZEy zstB&An)OEI++lRT#Hlh}UB$9<-Hzd8lIS5XI}*ROYkwyxo2af1rQ#HnQ0T zR2@OKh)y$+F&Nv{BW1>z$LF$=@)s{Ld0(ZV9Z zzM845TA3-EMVYlWE|c(WAy+XjwRs3!YCstc7FncSsY#7)obT^aW|Y4c`Jf;7ahW$T zi~JX#EEg%pM`39Z6$GkZQ=k{$`b*|2qI20?<>Fp25LVAHi+v7tseMe_U976qRvpf)$F6Qd~T-7YiS!SruRUMdRu5gh8Ba`w?_I=zI(jhDPEK=bgalI_ehh5cxzZ4YJgk@L3H56LS zMO{3%&K8_8W|vBu+#WA{*=;R}_BgFa6+`n2yMu~iNGX%G5mQ;lGDQSaB}vYcs}UpFk!omoxrAx5PVQpGLT@|7*QVqsey`0k}*slUXT0e7=5 zsY+-~6!_eXWp7^1YjIGcddQS>`2p9pS}f+PIU-}hohMwYvvegIl|;6@vZoERjOqhJ zUUqYTrc9JwR;31_;=*NJj!d`Y6$(>5h`l&Ps)4|($1;taV$1F?1?=oRE%uC(-q=8) znprzNm|+cQ);Yn9In{DrNOysqW0qMqP+^m(#8gH`1@ zflAaMXA7cSIjDwfsaM&rOA8?_oGxrY?o&wb?{niil(ncaQ%%9@OunC^K_zg7DF-9E zbgLHgV~oZ)7o(Eq%=mzUXT z-mEBOR&#iF<*00^WhNBID8Hi0afQ2ONDHtMH8vL8ab8(b$fpzE3Sws_y=!~$lO$3G z8kLXgOc}3wD=MLMOjPgK9Fwqa)IFQ)w)Ife&KsWt?7Qe#j)m%^w_0TatFi+IYElLSD+&rh0+vreHk6P z!;X0A*zpy!urU55A&#pFo#DBx@cmJVvnIBZr;s26!G58?ZzUE`^5boO|PJQU5ci&7;vl$(@IydNq3IZ9a;!jm?r~Nh!&m z*@EkWHtX6G+?6;LYL zvvo6qpw6}BICd;5ZH`!(*eYC5M|4xKE(ZJOSVTN>&V*uJRJlgqYW z*56ZUUtXLZj9ap}eJL?p7hLT+;7<>xPMO--KINkJ&d#8-bNbYaCQX@k?v!y0GnHyP zA)!#Aa4wdo2Vtc*!wtg>hf^+^c4-f%<$MRXcC+Y>x->`|>c;HyyQbgO(}8&C`SK z%(z7h7R^oA?d+H`ZVrb_{G@$3H%HTL6rIfJK3BL{d8>@Y%v`a2Ui*bfKe2-&x6dtf z6_vTC2N$l)RmWY|?ymAIpG%5i7U7-C{7dp2p7QPU5L#t=P$=2Q%FL-32kz_4w!+Mr zQ-a%W3&75a7mpit-CEyRUsu~RvQ;;&4c|BH-&9|}f77dXY^r^wwzq+Qjv*>bGDp*~dGSsM=cvavqY>dsd~>l-DKo$Puu z9S3=k3K59A6;U zhDWwa0@z6X&e}ePVpp|om_~iDw%ITl^3^iFMPhoI9(!Qm&e}H2?)AGcH;ZWA;nXbH zuo%Sx@2>4MOeLXjNZCQe13eJ_HnzT{zP>&r1+d@RF12E@nwBp}rM5%t*S68wO~wqh z$6#{@UD*Q*h;wz`tdVFGAr6~5QqzlcFE}%-COzylxYCg0*3BWM@3FRntw|!@PaAA1 zX5VVVuYh%-3g>#-yf{I?&AZkT+vS?-CTTxk|b+qgV2U{fD`ua&N$FMNdA`>((n~?_?Ol5cNaf4R&iDijuLv82C z*4i%r3WbkIPa93LLkwT0DQ${*-NvO}VzApW`PyT$0|P4rVecvg{gi9ME-|N$PKOlO zhDZzhFb#ya8+&5^Bf}a#G;;s`P1-SL%PTD3#t^lo9^@6fc_X_^i4o6vvbGBbB0av5 zK~8)lTT>!`Bg5jg5QcYaSs8Jg^=mdtHM_*CcYM^0Y^2kpk)ith<~_~6e*=?neuHf} zf(vV?h=r}%P{0$kW2eZr;l~M6d$jhrBu7$^Wg65#bd@n9W7-~-V!u>-RIlM3U?1@p2lP_m1Z>IE+-HJe{ocfO+hUCmI!Si0W^iYzBT^)1a=@2EV!G090hUJ>JLK)kXq(8Ei zgdoSW=@UmpJfoZCWQjww?>E;)R^uwJNIgmg`_PK2Z)V+QnzSoTZAh6DD=R41*HKgu z@%JGub}YAQHb?V+>C8e&H1jp;*b}(G)L@xHc3%D zGDga?`P^$ZH2_iAT3x!qc#vs&0Cq7fpT?$|Yp6J42TCr?L#Wgg$kO`7o-zF*3HEmA z6ATzs4AiN`7L9TJjG`3CR0Hf*0^3>J&VDGKWzj7iIyLv05uRBIVk%PxB|4i@8;qjS zA!6yWNk34kh~!T#A`xyOBKkA11dz7RsOE04&=!i8nB&NWD4T+Wl5~T6OYKd)Muifu z^i<*r+JhEMx9+E4?}y5B;#l6~H|hD)8*Lfs6D{GDu?p&`azfQBmXzp+5|NONpL8|C*&U2mU>ICpYbNyKOa zwlcwxO(}QQNz<`qrNba|QVMAi?a5vm#Jj}6UCB(Qi*_z?VQ)Yy>$UD7?eN8)0pe9P z7Zw7OPEhG8JV^>xlHMN^j#Xp$(o1R$V9}jsouI^m9GV7Mi0B^F2X*bTf72O_6?9W@sMD9~)!2+csXamsHS3J}8Y5Z*VTZrB(%A z5+PD7sn6N|Bjsz``UMY_|W2B(PItX&~F zTQTbZg_YN~!?uhksC|(qmn9Ob^nPSyE=v4PE!O%aNIO!SwbxQohwsUZq&MqA3~DH| z<@)lRw1>xS_TaMJsePwEUDo!rwE2jcXje9-;5EdPNK%bmtgP&nQ~(FAJ9X5@YFkFO z#un#hYtc1mLk5^A>gAw<4Iy0bp%Zn)ev{MK`O;I#*HM{0YsQL>0!wnhi=4x7!ltY>)KnuEcR7IH_tXsti$z91noNL31Ud~nB8C_DA zvkWTW!rd?&P=>kRv9u?bMm8$<5@2dN2(UOI+|{c3X^EM2XQ>qJ!jKH!E#eh8+%ft+ zOs#V~C0)g4a>9>h@b@KJMJy^xVJEQVe$2Er8+Z0`Qn5xSPU|pj-&zLMBdP`2z+QhF zE-A48$%;EVGE-!*5r$$tk_OYh-pE#l|GJ|S&xkUEMCDA4q7y%}M*+U-w*&(xwu(|j z;}(FL2qLt_yOv)41X5?KbCWb{rx}(YWvzj|AK<|-HqK~C2$f8*b<4@k_xJ7?b zF$ax1bGIzmk&-a{*qXXgh=>R)OGmO;85@Y9{20hC5@nDT*sdfhQQE!RP-e~6x{CdE zoHbmo!+~Jc|G=hV##&|L-XbY>kXc*~hf%V#4j78zv=PH(c6Q0+I23nJCuuFsrW7`{ z;UOFS<1p*Bl|(LQEzt$usDNA_jLIA)v>LX;=9~W!0()T<``ek1(=I?M_URHuwxd&z z&0ms5TuY>^Hl-W3ShLwFn%^@d5%IqlOycFXR#F&!Bfngrn5N>oh4-h}Llwjrss))m zm5f#Sb+03O&TckiPHZ{)`qv+=u;pub=4g4!I568@s-w#K*bmSHSv_`f*;cF&s~yZ^ zkLHN%P}k0>147ceo=N_@XcL)tYkYowcv%360A_ZOM^bg34a? R3t`kByXU_E;073x`CneH+kOB5 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fr/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/fr/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index a002a221c3a24b1893c196e680438d9fc3ccd4e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26064 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/it/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/it/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index b1e86ba36506e6836541e73ddf11bf0b4f7eb90a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19582 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ja/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ja/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 8b4d4f8f1c7e70024f7185e6019910541b7ecf29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23380 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/kk/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/kk/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index c23fc213ec658a975c278d566f36c46befd873dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10823 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ko/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ko/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 8bd529eaa23f49b72f70541feb96789cacfd9fc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21724 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%0DBKKmMqw=hq~jUu*Q_TKj~SH?9vN*TC41i&4jL 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 CF(0h} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/nl/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/nl/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index b45a90d4c0fc1658ec9ee28ef3f0cbabeb119a67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17138 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/pt_BR/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/pt_BR/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 8ca22918dc173cab887f24e099acf1dfd4d6afa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16495 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 Y6FJV~_(v8wbOax|mIyX6{ygsg0D+8CRsaA1 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ru/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/ru/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 2295ff8d1489a3774c6744895356393f54c03e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26950 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/sk/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/sk/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index 6732ff6e08a2aee22762fcf347e60fdd33e714ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21075 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 diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/uk/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/uk/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index f6ce9e4ae6a11f281fae03699b97bea8e670175c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6875 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 LJ0Y84Tbud+p%)k! diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/zh_TW/LC_MESSAGES/dash-to-panel.mo b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/locale/zh_TW/LC_MESSAGES/dash-to-panel.mo deleted file mode 100644 index c82af66a3d94399bbd2ddf566c50d1a3319cbf72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14647 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 tye!qYM`Glt^M-xZurH?QWELK{|i Titlebar Buttons > Minimize & Maximize.\n\nFor the best support, please report any issues on Github. Dash-to-panel is developed and maintained by @jderose9 and @charlesg99.", - "extension-id": "dash-to-panel", - "gettext-domain": "dash-to-panel", - "name": "Dash to Panel", - "shell-version": [ - "45" - ], - "url": "https://github.com/home-sweet-gnome/dash-to-panel", - "uuid": "dash-to-panel@jderose9.github.com", - "version": 59 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/overview.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/overview.js deleted file mode 100644 index e4f4961..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/overview.js +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import * as Intellihide from './intellihide.js'; -import * as Utils from './utils.js'; - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js'; -import {WindowPreview} from 'resource:///org/gnome/shell/ui/windowPreview.js'; -import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; -import {SETTINGS} from './extension.js'; - -const GS_HOTKEYS_KEY = 'switch-to-application-'; - -// When the dash is shown, workspace window preview bottom labels go over it (default -// gnome-shell behavior), but when the extension hides the dash, leave some space -// so those labels don't go over a bottom panel -const LABEL_MARGIN = 60; - -//timeout names -const T1 = 'swipeEndTimeout'; -const T2 = 'numberOverlayTimeout'; - -export const Overview = class { - - constructor() { - this._injectionManager = new InjectionManager(); - this._numHotkeys = 10; - } - - enable (primaryPanel) { - this._panel = primaryPanel; - this.taskbar = primaryPanel.taskbar; - - this._injectionsHandler = new Utils.InjectionsHandler(); - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._timeoutsHandler = new Utils.TimeoutsHandler(); - - this._optionalWorkspaceIsolation(); - this._optionalHotKeys(); - this._optionalNumberOverlay(); - this._optionalClickToExit(); - - this._toggleDash(); - this._adaptAlloc(); - - this._signalsHandler.add([ - SETTINGS, - [ - 'changed::stockgs-keep-dash', - 'changed::panel-sizes' - ], - () => this._toggleDash() - ]); - } - - disable() { - this._signalsHandler.destroy(); - this._injectionsHandler.destroy(); - this._timeoutsHandler.destroy(); - this._injectionManager.clear(); - - this._toggleDash(true); - - // Remove key bindings - this._disableHotKeys(); - this._disableExtraShortcut(); - this._disableClickToExit(); - } - - _toggleDash(visible) { - if (visible === undefined) { - visible = SETTINGS.get_boolean('stockgs-keep-dash'); - } - - let visibilityFunc = visible ? 'show' : 'hide'; - let height = visible ? -1 : LABEL_MARGIN * Utils.getScaleFactor(); - let overviewControls = Main.overview._overview._controls; - - overviewControls.dash[visibilityFunc](); - overviewControls.dash.set_height(height); - } - - _adaptAlloc() { - let overviewControls = Main.overview._overview._controls - - this._injectionManager.overrideMethod(Object.getPrototypeOf(overviewControls), 'vfunc_allocate', - (originalAllocate) => - (box) => { - let focusedPanel = this._panel.panelManager.focusedMonitorPanel - - if (focusedPanel) { - let position = focusedPanel.geom.position - let isBottom = position == St.Side.BOTTOM - - if (focusedPanel.intellihide?.enabled) { - // Panel intellihide is enabled (struts aren't taken into account on overview allocation), - // dynamically modify the overview box to follow the reveal/hide animation - let { transitioning, finalState, progress } = overviewControls._stateAdjustment.getStateTransitionParams() - let size = focusedPanel.geom[focusedPanel.checkIfVertical() ? 'w' : 'h'] * - (transitioning ? Math.abs((finalState != 0 ? 0 : 1) - progress) : 1) - - if (isBottom || position == St.Side.RIGHT) - box[focusedPanel.fixedCoord.c2] -= size - else - box[focusedPanel.fixedCoord.c1] += size - } else if (isBottom) - // The default overview allocation is very good and takes into account external - // struts, everywhere but the bottom where the dash is usually fixed anyway. - // If there is a bottom panel under the dash location, give it some space here - box.y2 -= focusedPanel.geom.h - } - - originalAllocate.call(overviewControls, box) - } - ); - } - - /** - * Isolate overview to open new windows for inactive apps - */ - _optionalWorkspaceIsolation() { - let label = 'optionalWorkspaceIsolation'; - - let enable = () => { - this._injectionsHandler.removeWithLabel(label); - - this._injectionsHandler.addWithLabel(label, [ - Shell.App.prototype, - 'activate', - IsolatedOverview - ]); - - this._signalsHandler.removeWithLabel(label); - - this._signalsHandler.addWithLabel(label, [ - global.window_manager, - 'switch-workspace', - () => this._panel.panelManager.allPanels.forEach(p => p.taskbar.handleIsolatedWorkspaceSwitch()) - ]); - } - - let disable = () => { - this._signalsHandler.removeWithLabel(label); - this._injectionsHandler.removeWithLabel(label); - } - - function IsolatedOverview() { - // These lines take care of Nautilus for icons on Desktop - let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - let windows = this.get_windows().filter(w => w.get_workspace().index() == activeWorkspace.index()); - - if (windows.length > 0 && - (!(windows.length == 1 && windows[0].skip_taskbar) || - this.is_on_workspace(activeWorkspace))) - return Main.activateWindow(windows[0]); - - return this.open_new_window(-1); - } - - this._signalsHandler.add([ - SETTINGS, - 'changed::isolate-workspaces', - () => { - this._panel.panelManager.allPanels.forEach(p => p.taskbar.resetAppIcons()); - - if (SETTINGS.get_boolean('isolate-workspaces')) - enable(); - else - disable(); - } - ]); - - if (SETTINGS.get_boolean('isolate-workspaces')) - enable(); - } - - // Hotkeys - _activateApp(appIndex, modifiers) { - let seenApps = {}; - let apps = []; - - this.taskbar._getAppIcons().forEach(appIcon => { - if (!seenApps[appIcon.app] || this.taskbar.allowSplitApps) { - apps.push(appIcon); - } - - seenApps[appIcon.app] = (seenApps[appIcon.app] || 0) + 1; - }); - - this._showOverlay(); - - if (appIndex < apps.length) { - let appIcon = apps[appIndex]; - let seenAppCount = seenApps[appIcon.app]; - let windowCount = appIcon.window || appIcon._hotkeysCycle ? seenAppCount : appIcon._nWindows; - - if (SETTINGS.get_boolean('shortcut-previews') && windowCount > 1 && - !(modifiers & ~(Clutter.ModifierType.MOD1_MASK | Clutter.ModifierType.SUPER_MASK))) { //ignore the alt (MOD1_MASK) and super key (SUPER_MASK) - if (this._hotkeyPreviewCycleInfo && this._hotkeyPreviewCycleInfo.appIcon != appIcon) { - this._endHotkeyPreviewCycle(); - } - - if (!this._hotkeyPreviewCycleInfo) { - this._hotkeyPreviewCycleInfo = { - appIcon: appIcon, - currentWindow: appIcon.window, - keyFocusOutId: appIcon.connect('key-focus-out', () => appIcon.grab_key_focus()), - capturedEventId: global.stage.connect('captured-event', (actor, e) => { - if (e.type() == Clutter.EventType.KEY_RELEASE && e.get_key_symbol() == (Clutter.KEY_Super_L || Clutter.Super_L)) { - this._endHotkeyPreviewCycle(true); - } - - return Clutter.EVENT_PROPAGATE; - }) - }; - - appIcon._hotkeysCycle = appIcon.window; - appIcon.window = null; - appIcon._previewMenu.open(appIcon, true); - appIcon.grab_key_focus(); - } - - appIcon._previewMenu.focusNext(); - } else { - // Activate with button = 1, i.e. same as left click - let button = 1; - this._endHotkeyPreviewCycle(); - appIcon.activate(button, modifiers, !this.taskbar.allowSplitApps); - } - } - } - - _endHotkeyPreviewCycle(focusWindow) { - if (this._hotkeyPreviewCycleInfo) { - global.stage.disconnect(this._hotkeyPreviewCycleInfo.capturedEventId); - this._hotkeyPreviewCycleInfo.appIcon.disconnect(this._hotkeyPreviewCycleInfo.keyFocusOutId); - - if (focusWindow) { - this._hotkeyPreviewCycleInfo.appIcon._previewMenu.activateFocused(); - } else - this._hotkeyPreviewCycleInfo.appIcon._previewMenu.close() - - this._hotkeyPreviewCycleInfo.appIcon.window = this._hotkeyPreviewCycleInfo.currentWindow; - delete this._hotkeyPreviewCycleInfo.appIcon._hotkeysCycle; - this._hotkeyPreviewCycleInfo = 0; - } - } - - _optionalHotKeys() { - this._hotKeysEnabled = false; - if (SETTINGS.get_boolean('hot-keys')) - this._enableHotKeys(); - - this._signalsHandler.add([ - SETTINGS, - 'changed::hot-keys', - () => { - if (SETTINGS.get_boolean('hot-keys')) - this._enableHotKeys(); - else - this._disableHotKeys(); - } - ]); - } - - _resetHotkeys() { - this._disableHotKeys(); - this._enableHotKeys(); - } - - _enableHotKeys() { - if (this._hotKeysEnabled) - return; - - //3.32 introduced app hotkeys, disable them to prevent conflicts - if (Main.wm._switchToApplication) { - for (let i = 1; i < 10; ++i) { - Utils.removeKeybinding(GS_HOTKEYS_KEY + i); - } - } - - // Setup keyboard bindings for taskbar elements - let shortcutNumKeys = SETTINGS.get_string('shortcut-num-keys'); - let bothNumKeys = shortcutNumKeys == 'BOTH'; - let keys = []; - let prefixModifiers = Clutter.ModifierType.SUPER_MASK - - if (SETTINGS.get_string('hotkey-prefix-text') == 'SuperAlt') - prefixModifiers |= Clutter.ModifierType.MOD1_MASK - - if (bothNumKeys || shortcutNumKeys == 'NUM_ROW') { - keys.push('app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-'); // Regular numbers - } - - if (bothNumKeys || shortcutNumKeys == 'NUM_KEYPAD') { - keys.push('app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-'); // Key-pad numbers - } - - keys.forEach( function(key) { - let modifiers = prefixModifiers - - // for some reason, in gnome-shell >= 40 Clutter.get_current_event() is now empty - // for keyboard events. Create here the modifiers that are needed in appicon.activate - modifiers |= (key.indexOf('-shift-') >= 0 ? Clutter.ModifierType.SHIFT_MASK : 0) - modifiers |= (key.indexOf('-ctrl-') >= 0 ? Clutter.ModifierType.CONTROL_MASK : 0) - - for (let i = 0; i < this._numHotkeys; i++) { - let appNum = i; - - Utils.addKeybinding(key + (i + 1), SETTINGS, () => this._activateApp(appNum, modifiers)); - } - }, this); - - this._hotKeysEnabled = true; - - if (SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS') - this.taskbar.toggleNumberOverlay(true); - } - - _disableHotKeys() { - if (!this._hotKeysEnabled) - return; - - let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-', // Regular numbers - 'app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-']; // Key-pad numbers - keys.forEach( function(key) { - for (let i = 0; i < this._numHotkeys; i++) { - Utils.removeKeybinding(key + (i + 1)); - } - }, this); - - if (Main.wm._switchToApplication) { - let gsSettings = new Gio.Settings({ schema_id: WindowManager.SHELL_KEYBINDINGS_SCHEMA }); - - for (let i = 1; i < 10; ++i) { - Utils.addKeybinding(GS_HOTKEYS_KEY + i, gsSettings, Main.wm._switchToApplication.bind(Main.wm)); - } - } - - this._hotKeysEnabled = false; - - this.taskbar.toggleNumberOverlay(false); - } - - _optionalNumberOverlay() { - // Enable extra shortcut - if (SETTINGS.get_boolean('hot-keys')) - this._enableExtraShortcut(); - - this._signalsHandler.add([ - SETTINGS, - 'changed::hot-keys', - this._checkHotkeysOptions.bind(this) - ], [ - SETTINGS, - 'changed::hotkeys-overlay-combo', - () => { - if (SETTINGS.get_boolean('hot-keys') && SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS') - this.taskbar.toggleNumberOverlay(true); - else - this.taskbar.toggleNumberOverlay(false); - } - ], [ - SETTINGS, - 'changed::shortcut-num-keys', - () => this._resetHotkeys() - ]); - } - - _checkHotkeysOptions() { - if (SETTINGS.get_boolean('hot-keys')) - this._enableExtraShortcut(); - else - this._disableExtraShortcut(); - } - - _enableExtraShortcut() { - Utils.addKeybinding('shortcut', SETTINGS, () => this._showOverlay(true)); - } - - _disableExtraShortcut() { - Utils.removeKeybinding('shortcut'); - } - - _showOverlay(overlayFromShortcut) { - //wait for intellihide timeout initialization - if (!this._panel.intellihide) { - return; - } - - // Restart the counting if the shortcut is pressed again - let hotkey_option = SETTINGS.get_string('hotkeys-overlay-combo'); - - if (hotkey_option === 'NEVER') - return; - - if (hotkey_option === 'TEMPORARILY' || overlayFromShortcut) - this.taskbar.toggleNumberOverlay(true); - - this._panel.intellihide.revealAndHold(Intellihide.Hold.TEMPORARY); - - let timeout = SETTINGS.get_int('overlay-timeout'); - - if (overlayFromShortcut) { - timeout = SETTINGS.get_int('shortcut-timeout'); - } - - // Hide the overlay/dock after the timeout - this._timeoutsHandler.add([T2, timeout, () => { - if (hotkey_option != 'ALWAYS') { - this.taskbar.toggleNumberOverlay(false); - } - - this._panel.intellihide.release(Intellihide.Hold.TEMPORARY); - }]); - } - - _optionalClickToExit() { - this._clickToExitEnabled = false; - if (SETTINGS.get_boolean('overview-click-to-exit')) - this._enableClickToExit(); - - this._signalsHandler.add([ - SETTINGS, - 'changed::overview-click-to-exit', - () => { - if (SETTINGS.get_boolean('overview-click-to-exit')) - this._enableClickToExit(); - else - this._disableClickToExit(); - } - ]); - } - - _enableClickToExit() { - if (this._clickToExitEnabled) - return; - - this._signalsHandler.addWithLabel('click-to-exit', [ - Main.layoutManager.overviewGroup, - 'button-release-event', - () => { - let [x, y] = global.get_pointer(); - let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); - - if (pickedActor) { - let parent = pickedActor.get_parent(); - - if ( - ( - pickedActor.has_style_class_name && - pickedActor.has_style_class_name('apps-scroll-view') && - !pickedActor.has_style_pseudo_class('first-child') - ) || ( - parent?.has_style_class_name && - parent.has_style_class_name('window-picker') - ) || - Main.overview._overview._controls._searchEntryBin.contains(pickedActor) || - pickedActor instanceof WindowPreview - ) - return Clutter.EVENT_PROPAGATE - } - - Main.overview.toggle() - } - ]); - - this._clickToExitEnabled = true; - } - - _disableClickToExit() { - if (!this._clickToExitEnabled) - return; - - this._signalsHandler.removeWithLabel('click-to-exit') - - this._clickToExitEnabled = false; - } - - _onSwipeBegin() { - this._swiping = true; - return true; - } - - _onSwipeEnd() { - this._timeoutsHandler.add([ - T1, - 0, - () => this._swiping = false - ]); - return true; - } - -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panel.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panel.js deleted file mode 100644 index b2f74f5..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panel.js +++ /dev/null @@ -1,1258 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * - * Code to re-anchor the panel was taken from Thoma5 BottomPanel: - * https://github.com/Thoma5/gnome-shell-extension-bottompanel - * - * Pattern for moving clock based on Frippery Move Clock by R M Yorston - * http://frippery.org/extensions/ - * - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import * as AppIcons from './appIcons.js'; -import * as Utils from './utils.js'; -import * as Taskbar from './taskbar.js'; -import * as TaskbarItemContainer from './taskbar.js'; -import * as Pos from './panelPositions.js'; -import * as PanelSettings from './panelSettings.js'; -import * as PanelStyle from './panelStyle.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'; -import * as CtrlAltTab from 'resource:///org/gnome/shell/ui/ctrlAltTab.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import St from 'gi://St'; -import Meta from 'gi://Meta'; -import Pango from 'gi://Pango'; -import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import Shell from 'gi://Shell'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as DateMenu from 'resource:///org/gnome/shell/ui/dateMenu.js'; -import * as Volume from 'resource:///org/gnome/shell/ui/status/volume.js'; -import * as Progress from './progress.js'; - -import * as Intellihide from './intellihide.js'; -import * as Transparency from './transparency.js'; -import {SETTINGS, DESKTOPSETTINGS, PERSISTENTSTORAGE} from './extension.js'; -import {gettext as _, InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; - -let tracker = Shell.WindowTracker.get_default(); -export const panelBoxes = ['_leftBox', '_centerBox', '_rightBox']; - -//timeout names -const T2 = 'startIntellihideTimeout'; -const T4 = 'showDesktopTimeout'; -const T5 = 'trackerFocusAppTimeout'; -const T6 = 'scrollPanelDelayTimeout'; -const T7 = 'waitPanelBoxAllocation'; - -export const Panel = GObject.registerClass({ -}, class Panel extends St.Widget { - - _init(panelManager, monitor, panelBox, isStandalone) { - super._init({ layout_manager: new Clutter.BinLayout() }); - - this._timeoutsHandler = new Utils.TimeoutsHandler(); - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._injectionManager = new InjectionManager(); - - this.panelManager = panelManager; - this.panelStyle = new PanelStyle.PanelStyle(); - - this.monitor = monitor; - this.panelBox = panelBox; - - // when the original gnome-shell top panel is kept, all panels are "standalone", - // so in this case use isPrimary to get the panel on the primary dtp monitor, which - // might be different from the system's primary monitor. - this.isStandalone = isStandalone; - this.isPrimary = !isStandalone || (SETTINGS.get_boolean('stockgs-keep-top-panel') && - monitor == panelManager.dtpPrimaryMonitor); - - this._sessionStyle = null; - this._unmappedButtons = []; - this._elementGroups = []; - - let systemMenuInfo = Utils.getSystemMenuInfo(); - - if (isStandalone) { - this.panel = new SecondaryPanel({ name: 'panel', reactive: true }); - this.statusArea = this.panel.statusArea = {}; - - //next 3 functions are needed by other extensions to add elements to the secondary panel - this.panel.addToStatusArea = function(role, indicator, position, box) { - return Main.panel.addToStatusArea.call(this, role, indicator, position, box); - }; - - this.panel._addToPanelBox = function(role, indicator, position, box) { - Main.panel._addToPanelBox.call(this, role, indicator, position, box); - }; - - this.panel._onMenuSet = function(indicator) { - Main.panel._onMenuSet.call(this, indicator); - }; - - this._leftBox = this.panel._leftBox = new St.BoxLayout({ name: 'panelLeft' }); - this._centerBox = this.panel._centerBox = new St.BoxLayout({ name: 'panelCenter' }); - this._rightBox = this.panel._rightBox = new St.BoxLayout({ name: 'panelRight' }); - - this.menuManager = this.panel.menuManager = new PopupMenu.PopupMenuManager(this.panel); - - this._setPanelMenu(systemMenuInfo.name, systemMenuInfo.constructor, this.panel); - this._setPanelMenu('dateMenu', DateMenu.DateMenuButton, this.panel); - this._setPanelMenu('activities', Main.panel.statusArea.activities.constructor, this.panel); - - this.panel.add_child(this._leftBox); - this.panel.add_child(this._centerBox); - this.panel.add_child(this._rightBox); - } else { - this.panel = Main.panel; - this.statusArea = Main.panel.statusArea; - this.menuManager = Main.panel.menuManager; - - panelBoxes.forEach(p => this[p] = Main.panel[p]); - - ['activities', systemMenuInfo.name, 'dateMenu'].forEach(b => { - let container = this.statusArea[b].container; - let parent = container.get_parent(); - - container._dtpOriginalParent = parent; - parent ? parent.remove_child(container) : null; - this.panel.add_child(container); - }); - } - - // Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of - // its behavior is handled by the taskbar, but its positioning is done at the panel level - this.showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this); - this.panel.add_child(this.showAppsIconWrapper.realShowAppsIcon); - - this.panel._delegate = this; - - this.add_child(this.panel); - - if (Main.panel._onButtonPress || Main.panel._tryDragWindow) { - this._signalsHandler.add([ - this.panel, - [ - 'button-press-event', - 'touch-event' - ], - this._onButtonPress.bind(this) - ]); - } - - if (Main.panel._onKeyPress) { - this._signalsHandler.add([this.panel, 'key-press-event', Main.panel._onKeyPress.bind(this)]); - } - - Main.ctrlAltTabManager.addGroup(this, _("Top Bar")+" "+ monitor.index, 'focus-top-bar-symbolic', - { sortGroup: CtrlAltTab.SortGroup.TOP }); - } - - enable () { - let { name: systemMenuName } = Utils.getSystemMenuInfo(); - - if (this.statusArea[systemMenuName] && this.statusArea[systemMenuName]._volumeOutput) { - Utils.getIndicators(this.statusArea[systemMenuName]._volumeOutput)._dtpIgnoreScroll = 1; - } - - this.geom = this.getGeometry(); - - this._setPanelPosition(); - - if (!this.isStandalone) { - this._injectionManager.overrideMethod(Object.getPrototypeOf(this.panel), 'vfunc_allocate', () => (box) => this._mainPanelAllocate(box)); - - // remove the extra space before the clock when the message-indicator is displayed - if (DateMenu.IndicatorPad) { - this._injectionManager.overrideMethod(DateMenu.IndicatorPad.prototype, 'vfunc_get_preferred_width', () => () => [0,0]); - this._injectionManager.overrideMethod(DateMenu.IndicatorPad.prototype, 'vfunc_get_preferred_height', () => () => [0,0]); - } - } - - if (!DateMenu.IndicatorPad && this.statusArea.dateMenu) { - //3.36 switched to a size constraint applied on an anonymous child - let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child(); - - this._dateMenuIndicatorPadContraints = indicatorPad.get_constraints(); - indicatorPad.clear_constraints(); - } - - this.menuManager._oldChangeMenu = this.menuManager._changeMenu; - this.menuManager._changeMenu = (menu) => { - if (!SETTINGS.get_boolean('stockgs-panelbtn-click-only')) { - this.menuManager._oldChangeMenu(menu); - } - }; - - this.dynamicTransparency = new Transparency.DynamicTransparency(this); - - this.taskbar = new Taskbar.Taskbar(this); - - this.panel.add_child(this.taskbar.actor); - - this._setShowDesktopButton(true); - - this._setAllocationMap(); - - this.panel.add_style_class_name('dashtopanelMainPanel ' + this.getOrientation()); - - this._timeoutsHandler.add([T2, SETTINGS.get_int('intellihide-enable-start-delay'), () => this.intellihide = new Intellihide.Intellihide(this)]); - - this._signalsHandler.add( - // this is to catch changes to the theme or window scale factor - [ - Utils.getStageTheme(), - 'changed', - () => (this._resetGeometry(), this._setShowDesktopButtonStyle()), - ], - [ - // sync hover after a popupmenu is closed - this.taskbar, - 'menu-closed', - () => this.panel.sync_hover() - ], - [ - Main.overview, - [ - 'showing', - 'hiding' - ], - () => this._adjustForOverview() - ], - [ - Main.overview, - 'hidden', - () => { - if (this.isPrimary) { - //reset the primary monitor when exiting the overview - this.panelManager.setFocusedMonitor(this.monitor); - } - } - ], - [ - this.statusArea.activities, - 'captured-event', - (actor, e) => { - if (e.type() == Clutter.EventType.BUTTON_PRESS || e.type() == Clutter.EventType.TOUCH_BEGIN) { - //temporarily use as primary the monitor on which the activities btn was clicked - this.panelManager.setFocusedMonitor(this.monitor); - } - } - ], - [ - this._centerBox, - 'actor-added', - () => this._onBoxActorAdded(this._centerBox) - ], - [ - this._rightBox, - 'actor-added', - () => this._onBoxActorAdded(this._rightBox) - ], - [ - this.panel, - 'scroll-event', - this._onPanelMouseScroll.bind(this) - ], - [ - Main.layoutManager, - 'startup-complete', - () => this._resetGeometry() - ] - ); - - this._bindSettingsChanges(); - - this.panelStyle.enable(this); - - if (this.checkIfVertical()) { - this._signalsHandler.add([ - this.panelBox, - 'notify::visible', - () => { - if (this.panelBox.visible) { - this._refreshVerticalAlloc(); - } - } - ]); - - if (this.statusArea.dateMenu) { - this._formatVerticalClock(); - - this._signalsHandler.add([ - this.statusArea.dateMenu._clock, - 'notify::clock', - () => this._formatVerticalClock() - ]); - } - } - - // Since we are usually visible but not usually changing, make sure - // most repaint requests don't actually require us to repaint anything. - // This saves significant CPU when repainting the screen. - this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); - - this._initProgressManager(); - } - - disable() { - this.panelStyle.disable(); - - this._timeoutsHandler.destroy(); - this._signalsHandler.destroy(); - - this.panel.remove_child(this.taskbar.actor); - - if (this.intellihide) { - this.intellihide.destroy(); - } - - this.dynamicTransparency.destroy(); - - this.progressManager.destroy(); - - this.taskbar.destroy(); - this.showAppsIconWrapper.destroy(); - - this.menuManager._changeMenu = this.menuManager._oldChangeMenu; - - this._unmappedButtons.forEach(a => this._disconnectVisibleId(a)); - - if (this.statusArea.dateMenu) { - this.statusArea.dateMenu._clockDisplay.text = this.statusArea.dateMenu._clock.clock; - this.statusArea.dateMenu._clockDisplay.clutter_text.set_width(-1); - - if (this._dateMenuIndicatorPadContraints) { - let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child(); - - this._dateMenuIndicatorPadContraints.forEach(c => indicatorPad.add_constraint(c)); - } - } - - this._setVertical(this.panel, false); - this._setVertical(this._centerBox, false); - this._setVertical(this._rightBox, false); - - let { name: systemMenuName } = Utils.getSystemMenuInfo(); - - if (!this.isStandalone) { - ['vertical', 'horizontal', 'dashtopanelMainPanel'].forEach(c => this.panel.remove_style_class_name(c)); - - if (!Main.sessionMode.isLocked) { - [['activities', 0], [systemMenuName, -1], ['dateMenu', 0]].forEach(b => { - let container = this.statusArea[b[0]].container; - let originalParent = container._dtpOriginalParent; - - this.panel.remove_child(container); - originalParent ? originalParent.insert_child_at_index(container, b[1]) : null; - delete container._dtpOriginalParent; - }); - } - - this._setShowDesktopButton(false); - - delete Utils.getIndicators(this.statusArea[systemMenuName]._volumeOutput)._dtpIgnoreScroll; - - this._injectionManager.clear(); - - this.panel._delegate = this.panel; - } else { - this._removePanelMenu('dateMenu'); - this._removePanelMenu(systemMenuName); - this._removePanelMenu('activities'); - } - - Main.ctrlAltTabManager.removeGroup(this); - } - - handleDragOver(source, actor, x, y, time) { - if (source == Main.xdndHandler) { - - // open overview so they can choose a window for focusing - // and ultimately dropping dragged item onto - if(Main.overview.shouldToggleByCornerOrButton()) - Main.overview.show(); - } - - return DND.DragMotionResult.CONTINUE; - } - - getPosition() { - let position = PanelSettings.getPanelPosition(SETTINGS, this.monitor.index); - - if (position == Pos.TOP) { - return St.Side.TOP; - } else if (position == Pos.RIGHT) { - return St.Side.RIGHT; - } else if (position == Pos.BOTTOM) { - return St.Side.BOTTOM; - } - - return St.Side.LEFT; - } - - checkIfVertical() { - let position = this.getPosition(); - - return (position == St.Side.LEFT || position == St.Side.RIGHT); - } - - getOrientation() { - return (this.checkIfVertical() ? 'vertical' : 'horizontal'); - } - - updateElementPositions() { - let panelPositions = this.panelManager.panelsElementPositions[this.monitor.index] || Pos.defaults; - - this._updateGroupedElements(panelPositions); - - this.panel.hide(); - this.panel.show(); - } - - _updateGroupedElements(panelPositions) { - let previousPosition = 0; - let previousCenteredPosition = 0; - let currentGroup = -1; - - this._elementGroups = []; - - panelPositions.forEach(pos => { - let allocationMap = this.allocationMap[pos.element]; - - if (allocationMap.actor) { - allocationMap.actor.visible = pos.visible; - - if (!pos.visible) { - return; - } - - let currentPosition = pos.position; - let isCentered = Pos.checkIfCentered(currentPosition); - - if (currentPosition == Pos.STACKED_TL && previousPosition == Pos.STACKED_BR) { - currentPosition = Pos.STACKED_BR; - } - - if (!previousPosition || - (previousPosition == Pos.STACKED_TL && currentPosition != Pos.STACKED_TL) || - (previousPosition != Pos.STACKED_BR && currentPosition == Pos.STACKED_BR) || - (isCentered && previousPosition != currentPosition && previousPosition != Pos.STACKED_BR)) { - this._elementGroups[++currentGroup] = { elements: [], index: this._elementGroups.length, expandableIndex: -1 }; - previousCenteredPosition = 0; - } - - if (pos.element == Pos.TASKBAR) { - this._elementGroups[currentGroup].expandableIndex = this._elementGroups[currentGroup].elements.length; - } - - if (isCentered && !this._elementGroups[currentGroup].isCentered) { - this._elementGroups[currentGroup].isCentered = 1; - previousCenteredPosition = currentPosition; - } - - this._elementGroups[currentGroup].position = previousCenteredPosition || currentPosition; - this._elementGroups[currentGroup].elements.push(allocationMap); - - allocationMap.position = currentPosition; - previousPosition = currentPosition; - } - }); - } - - _bindSettingsChanges() { - let isVertical = this.checkIfVertical(); - - this._signalsHandler.add( - [ - SETTINGS, - [ - 'changed::panel-sizes', - 'changed::group-apps' - ], - () => this._resetGeometry() - ], - [ - SETTINGS, - [ - 'changed::appicon-margin', - 'changed::appicon-padding' - ], - () => this.taskbar.resetAppIcons() - ], - [ - SETTINGS, - [ - 'changed::showdesktop-button-width', - 'changed::trans-use-custom-bg', - 'changed::desktop-line-use-custom-color', - 'changed::desktop-line-custom-color', - 'changed::trans-bg-color' - ], - () => this._setShowDesktopButtonStyle() - ], - [ - DESKTOPSETTINGS, - 'changed::clock-format', - () => { - this._clockFormat = null; - - if (isVertical) { - this._formatVerticalClock(); - } - } - ], - [ - SETTINGS, - 'changed::progress-show-bar', - () => this._initProgressManager() - ], - [ - SETTINGS, - 'changed::progress-show-count', - () => this._initProgressManager() - ] - ); - - if (isVertical) { - this._signalsHandler.add([SETTINGS, 'changed::group-apps-label-max-width', () => this._resetGeometry()]); - } - } - - _setPanelMenu(propName, constr, container) { - if (!this.statusArea[propName]) { - this.statusArea[propName] = this._getPanelMenu(propName, constr); - this.menuManager.addMenu(this.statusArea[propName].menu); - container.insert_child_at_index(this.statusArea[propName].container, 0); - } - } - - _removePanelMenu(propName) { - if (this.statusArea[propName]) { - let parent = this.statusArea[propName].container.get_parent(); - - if (parent) { - parent.remove_actor(this.statusArea[propName].container); - } - - //calling this.statusArea[propName].destroy(); is buggy for now, gnome-shell never - //destroys those panel menus... - //since we can't destroy the menu (hence properly disconnect its signals), let's - //store it so the next time a panel needs one of its kind, we can reuse it instead - //of creating a new one - let panelMenu = this.statusArea[propName]; - - this.menuManager.removeMenu(panelMenu.menu); - PERSISTENTSTORAGE[propName].push(panelMenu); - this.statusArea[propName] = null; - } - } - - _getPanelMenu(propName, constr) { - PERSISTENTSTORAGE[propName] = PERSISTENTSTORAGE[propName] || []; - - if (!PERSISTENTSTORAGE[propName].length) { - PERSISTENTSTORAGE[propName].push(new constr()); - } - - return PERSISTENTSTORAGE[propName].pop(); - } - - _adjustForOverview() { - let isFocusedMonitor = this.panelManager.checkIfFocusedMonitor(this.monitor); - let isOverview = !!Main.overview.visibleTarget; - let isOverviewFocusedMonitor = isOverview && isFocusedMonitor; - let isShown = !isOverview || isOverviewFocusedMonitor; - let actorData = Utils.getTrackedActorData(this.panelBox) - - // prevent the "chrome" to update the panelbox visibility while in overview - actorData.trackFullscreen = !isOverview - - this.panelBox[isShown ? 'show' : 'hide'](); - } - - _resetGeometry() { - this.geom = this.getGeometry(); - this._setPanelPosition(); - this.taskbar.resetAppIcons(true); - this.dynamicTransparency.updateExternalStyle(); - - if (this.intellihide && this.intellihide.enabled) { - this.intellihide.reset(); - } - - if (this.checkIfVertical()) { - this.showAppsIconWrapper.realShowAppsIcon.toggleButton.set_width(this.geom.w); - this._refreshVerticalAlloc(); - } - } - - getGeometry() { - let scaleFactor = Utils.getScaleFactor(); - let panelBoxTheme = this.panelBox.get_theme_node(); - let lrPadding = panelBoxTheme.get_padding(St.Side.RIGHT) + panelBoxTheme.get_padding(St.Side.LEFT); - let topPadding = panelBoxTheme.get_padding(St.Side.TOP); - let tbPadding = topPadding + panelBoxTheme.get_padding(St.Side.BOTTOM); - let position = this.getPosition(); - let length = PanelSettings.getPanelLength(SETTINGS, this.monitor.index) / 100; - let anchor = PanelSettings.getPanelAnchor(SETTINGS, this.monitor.index); - let anchorPlaceOnMonitor = 0; - let gsTopPanelOffset = 0; - let x = 0, y = 0; - let w = 0, h = 0; - - const panelSize = PanelSettings.getPanelSize(SETTINGS, this.monitor.index); - this.dtpSize = panelSize * scaleFactor; - - if (SETTINGS.get_boolean('stockgs-keep-top-panel') && Main.layoutManager.primaryMonitor == this.monitor) { - gsTopPanelOffset = Main.layoutManager.panelBox.height - topPadding; - } - - if (this.checkIfVertical()) { - if (!SETTINGS.get_boolean('group-apps')) { - // add window title width and side padding of _dtpIconContainer when vertical - this.dtpSize += SETTINGS.get_int('group-apps-label-max-width') + AppIcons.DEFAULT_PADDING_SIZE * 2 / scaleFactor; - } - - this.sizeFunc = 'get_preferred_height', - this.fixedCoord = { c1: 'x1', c2: 'x2' } - this.varCoord = { c1: 'y1', c2: 'y2' }; - - w = this.dtpSize; - h = this.monitor.height * length - tbPadding - gsTopPanelOffset; - } else { - this.sizeFunc = 'get_preferred_width'; - this.fixedCoord = { c1: 'y1', c2: 'y2' }; - this.varCoord = { c1: 'x1', c2: 'x2' }; - - w = this.monitor.width * length - lrPadding; - h = this.dtpSize; - } - - if (position == St.Side.TOP || position == St.Side.LEFT) { - x = this.monitor.x; - y = this.monitor.y + gsTopPanelOffset; - } else if (position == St.Side.RIGHT) { - x = this.monitor.x + this.monitor.width - this.dtpSize - lrPadding; - y = this.monitor.y + gsTopPanelOffset; - } else { //BOTTOM - x = this.monitor.x; - y = this.monitor.y + this.monitor.height - this.dtpSize - tbPadding; - } - - if (this.checkIfVertical()) { - let viewHeight = this.monitor.height - gsTopPanelOffset; - - if (anchor === Pos.MIDDLE) { - anchorPlaceOnMonitor = (viewHeight - h) / 2; - } else if (anchor === Pos.END) { - anchorPlaceOnMonitor = viewHeight - h; - } else { // Pos.START - anchorPlaceOnMonitor = 0; - } - y = y + anchorPlaceOnMonitor; - } else { - if (anchor === Pos.MIDDLE) { - anchorPlaceOnMonitor = (this.monitor.width - w) / 2; - } else if (anchor === Pos.END) { - anchorPlaceOnMonitor = this.monitor.width - w; - } else { // Pos.START - anchorPlaceOnMonitor = 0; - } - x = x + anchorPlaceOnMonitor; - } - - return { - x, y, - w, h, - lrPadding, - tbPadding, - position - }; - } - - _setAllocationMap() { - this.allocationMap = {}; - let setMap = (name, actor) => this.allocationMap[name] = { - actor: actor, - box: new Clutter.ActorBox() - }; - - setMap(Pos.SHOW_APPS_BTN, this.showAppsIconWrapper.realShowAppsIcon); - setMap(Pos.ACTIVITIES_BTN, this.statusArea.activities ? this.statusArea.activities.container : 0); - setMap(Pos.LEFT_BOX, this._leftBox); - setMap(Pos.TASKBAR, this.taskbar.actor); - setMap(Pos.CENTER_BOX, this._centerBox); - setMap(Pos.DATE_MENU, this.statusArea.dateMenu.container); - setMap(Pos.SYSTEM_MENU, this.statusArea[Utils.getSystemMenuInfo().name].container); - setMap(Pos.RIGHT_BOX, this._rightBox); - setMap(Pos.DESKTOP_BTN, this._showDesktopButton); - } - - _mainPanelAllocate(box) { - this.panel.set_allocation(box); - } - - vfunc_allocate(box) { - this.set_allocation(box); - - let fixed = 0; - let centeredMonitorGroup; - let panelAlloc = new Clutter.ActorBox({ x1: 0, y1: 0, x2: this.geom.w, y2: this.geom.h }); - let assignGroupSize = (group, update) => { - group.size = 0; - group.tlOffset = 0; - group.brOffset = 0; - - group.elements.forEach(element => { - if (!update) { - element.box[this.fixedCoord.c1] = panelAlloc[this.fixedCoord.c1]; - element.box[this.fixedCoord.c2] = panelAlloc[this.fixedCoord.c2]; - element.natSize = element.actor[this.sizeFunc](-1)[1]; - } - - if (!group.isCentered || Pos.checkIfCentered(element.position)) { - group.size += element.natSize; - } else if (element.position == Pos.STACKED_TL) { - group.tlOffset += element.natSize; - } else { // Pos.STACKED_BR - group.brOffset += element.natSize; - } - }); - - if (group.isCentered) { - group.size += Math.max(group.tlOffset, group.brOffset) * 2; - group.tlOffset = Math.max(group.tlOffset - group.brOffset, 0); - } - }; - let allocateGroup = (group, tlLimit, brLimit) => { - let startPosition = tlLimit; - let currentPosition = 0; - - if (group.expandableIndex >= 0) { - let availableSize = brLimit - tlLimit; - let expandable = group.elements[group.expandableIndex]; - let i = 0; - let l = this._elementGroups.length; - let tlSize = 0; - let brSize = 0; - - if (centeredMonitorGroup && (centeredMonitorGroup != group || expandable.position != Pos.CENTERED_MONITOR)) { - if (centeredMonitorGroup.index < group.index || (centeredMonitorGroup == group && expandable.position == Pos.STACKED_TL)) { - i = centeredMonitorGroup.index; - } else { - l = centeredMonitorGroup.index; - } - } - - for (; i < l; ++i) { - let refGroup = this._elementGroups[i]; - - if (i < group.index && (!refGroup.fixed || refGroup[this.varCoord.c2] > tlLimit)) { - tlSize += refGroup.size; - } else if (i > group.index && (!refGroup.fixed || refGroup[this.varCoord.c1] < brLimit)) { - brSize += refGroup.size; - } - } - - if (group.isCentered) { - availableSize -= Math.max(tlSize, brSize) * 2; - } else { - availableSize -= tlSize + brSize; - } - - if (availableSize < group.size) { - expandable.natSize -= (group.size - availableSize) * (group.isCentered && !Pos.checkIfCentered(expandable.position) ? .5 : 1); - assignGroupSize(group, true); - } - } - - if (group.isCentered) { - startPosition = tlLimit + (brLimit - tlLimit - group.size) * .5; - } else if (group.position == Pos.STACKED_BR) { - startPosition = brLimit - group.size; - } - - currentPosition = group.tlOffset + startPosition; - - group.elements.forEach(element => { - element.box[this.varCoord.c1] = Math.round(currentPosition); - element.box[this.varCoord.c2] = Math.round((currentPosition += element.natSize)); - - element.actor.allocate(element.box); - }); - - group[this.varCoord.c1] = startPosition; - group[this.varCoord.c2] = currentPosition; - group.fixed = 1; - ++fixed; - }; - - this.panel.allocate(panelAlloc); - - this._elementGroups.forEach(group => { - group.fixed = 0; - - assignGroupSize(group); - - if (group.position == Pos.CENTERED_MONITOR) { - centeredMonitorGroup = group; - } - }); - - if (centeredMonitorGroup) { - allocateGroup(centeredMonitorGroup, panelAlloc[this.varCoord.c1], panelAlloc[this.varCoord.c2]); - } - - let iterations = 0; //failsafe - while (fixed < this._elementGroups.length && ++iterations < 10) { - for (let i = 0, l = this._elementGroups.length; i < l; ++i) { - let group = this._elementGroups[i]; - - if (group.fixed) { - continue; - } - - let prevGroup = this._elementGroups[i - 1]; - let nextGroup = this._elementGroups[i + 1]; - let prevLimit = prevGroup && prevGroup.fixed ? prevGroup[this.varCoord.c2] : - centeredMonitorGroup && group.index > centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c2] : panelAlloc[this.varCoord.c1]; - let nextLimit = nextGroup && nextGroup.fixed ? nextGroup[this.varCoord.c1] : - centeredMonitorGroup && group.index < centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c1] : panelAlloc[this.varCoord.c2]; - - if (group.position == Pos.STACKED_TL) { - allocateGroup(group, panelAlloc[this.varCoord.c1], nextLimit); - } else if (group.position == Pos.STACKED_BR) { - allocateGroup(group, prevLimit, panelAlloc[this.varCoord.c2]); - } else if ((!prevGroup || prevGroup.fixed) && (!nextGroup || nextGroup.fixed)) { // CENTERED - allocateGroup(group, prevLimit, nextLimit); - } - } - } - } - - _setPanelPosition() { - let clipContainer = this.panelBox.get_parent(); - - this.set_size(this.geom.w, this.geom.h); - clipContainer.set_position(this.geom.x, this.geom.y); - - this._setVertical(this.panel, this.checkIfVertical()); - - // styles for theming - Object.keys(St.Side).forEach(p => { - let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase(); - - this.panel[(St.Side[p] == this.geom.position ? 'add' : 'remove') + '_style_class_name'](cssName); - }); - - this._setPanelClip(clipContainer); - - Main.layoutManager._updateHotCorners(); - Main.layoutManager._updatePanelBarrier(this); - } - - _setPanelClip(clipContainer) { - clipContainer = clipContainer || this.panelBox.get_parent(); - this._timeoutsHandler.add([T7, 0, () => Utils.setClip(clipContainer, clipContainer.x, clipContainer.y, this.panelBox.width, this.panelBox.height)]); - } - - _onButtonPress(actor, event) { - let type = event.type(); - let isPress = type == Clutter.EventType.BUTTON_PRESS; - let button = isPress ? event.get_button() : -1; - let [stageX, stageY] = event.get_coords(); - - if (button == 3 && global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, stageX, stageY) == this.panel) { - //right click on an empty part of the panel, temporarily borrow and display the showapps context menu - Main.layoutManager.setDummyCursorGeometry(stageX, stageY, 0, 0); - - this.showAppsIconWrapper.createMenu(); - this.showAppsIconWrapper.popupMenu(Main.layoutManager.dummyCursor); - - return Clutter.EVENT_STOP; - } else { - const targetActor = global.stage.get_event_actor(event); - - if (Main.modalCount > 0 || targetActor != actor || - (!isPress && type != Clutter.EventType.TOUCH_BEGIN) || - (isPress && button != 1)) { - return Clutter.EVENT_PROPAGATE; - } - } - - let params = this.checkIfVertical() ? [stageY, 'y', 'height'] : [stageX, 'x', 'width']; - let dragWindow = this._getDraggableWindowForPosition.apply(this, params.concat(['maximized_' + this.getOrientation() + 'ly'])); - - if (!dragWindow) - return Clutter.EVENT_PROPAGATE; - - global.display.begin_grab_op(dragWindow, - Meta.GrabOp.MOVING, - false, /* pointer grab */ - true, /* frame action */ - button, - event.get_state(), - event.get_time(), - stageX, stageY); - - return Clutter.EVENT_STOP; - } - - _getDraggableWindowForPosition(stageCoord, coord, dimension, maximizedProp) { - let workspace = Utils.getCurrentWorkspace(); - let allWindowsByStacking = global.display.sort_windows_by_stacking( - workspace.list_windows() - ).reverse(); - - return Utils.find(allWindowsByStacking, metaWindow => { - let rect = metaWindow.get_frame_rect(); - - return metaWindow.get_monitor() == this.monitor.index && - metaWindow.showing_on_its_workspace() && - metaWindow.get_window_type() != Meta.WindowType.DESKTOP && - metaWindow[maximizedProp] && - stageCoord > rect[coord] && stageCoord < rect[coord] + rect[dimension]; - }); - } - - _onBoxActorAdded(box) { - if (this.checkIfVertical()) { - this._setVertical(box, true); - } - } - - _refreshVerticalAlloc() { - this._setVertical(this._centerBox, true); - this._setVertical(this._rightBox, true); - this._formatVerticalClock(); - } - - _setVertical(actor, isVertical) { - let _set = (actor, isVertical) => { - if (!actor || actor instanceof Dash.DashItemContainer || actor instanceof TaskbarItemContainer.TaskbarItemContainer) { - return; - } - - if (actor instanceof St.BoxLayout) { - actor.vertical = isVertical; - } else if ((actor._delegate || actor) instanceof PanelMenu.ButtonBox && actor != this.statusArea.appMenu) { - let child = actor.get_first_child(); - - if (isVertical && !actor.visible && !actor._dtpVisibleId) { - this._unmappedButtons.push(actor); - actor._dtpVisibleId = actor.connect('notify::visible', () => { - this._disconnectVisibleId(actor); - this._refreshVerticalAlloc(); - }); - actor._dtpDestroyId = actor.connect('destroy', () => this._disconnectVisibleId(actor)); - } - - if (child) { - let [, natWidth] = actor.get_preferred_width(-1); - - child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START']; - actor.set_width(isVertical ? this.dtpSize : -1); - isVertical = isVertical && (natWidth > this.dtpSize); - actor[(isVertical ? 'add' : 'remove') + '_style_class_name']('vertical'); - } - } - - actor.get_children().forEach(c => _set(c, isVertical)); - }; - - _set(actor, false); - - if (isVertical) - _set(actor, isVertical); - } - - _disconnectVisibleId(actor) { - actor.disconnect(actor._dtpVisibleId); - actor.disconnect(actor._dtpDestroyId); - - delete actor._dtpVisibleId; - delete actor._dtpDestroyId; - - this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1); - } - - _formatVerticalClock() { - // https://github.com/GNOME/gnome-desktop/blob/master/libgnome-desktop/gnome-wall-clock.c#L310 - if (this.statusArea.dateMenu) { - let datetime = this.statusArea.dateMenu._clock.clock; - let datetimeParts = datetime.split(' '); - let time = datetimeParts[1]; - let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text; - let setClockText = (text, useTimeSeparator) => { - let stacks = text instanceof Array; - let separator = `\n ${useTimeSeparator ? '‧‧' : '—' } \n`; - - clockText.set_text((stacks ? text.join(separator) : text).trim()); - clockText.set_use_markup(stacks); - clockText.get_allocation_box(); - - return !clockText.get_layout().is_ellipsized(); - }; - - if (clockText.ellipsize == Pango.EllipsizeMode.NONE) { - //on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back - clockText.ellipsize = Pango.EllipsizeMode.END; - } - - clockText.natural_width = this.dtpSize; - - if (!time) { - datetimeParts = datetime.split(' '); - time = datetimeParts.pop(); - datetimeParts = [datetimeParts.join(' '), time]; - } - - if (!setClockText(datetime) && - !setClockText(datetimeParts) && - !setClockText(time)) { - let timeParts = time.split('∶'); - - if (!this._clockFormat) { - this._clockFormat = DESKTOPSETTINGS.get_string('clock-format'); - } - - if (this._clockFormat == '12h') { - timeParts.push.apply(timeParts, timeParts.pop().split(' ')); - } - - setClockText(timeParts, true); - } - } - } - - _setShowDesktopButton(add) { - if (add) { - if(this._showDesktopButton) - return; - - this._showDesktopButton = new St.Bin({ style_class: 'showdesktop-button', - reactive: true, - can_focus: true, - // x_fill: true, - // y_fill: true, - track_hover: true }); - - this._setShowDesktopButtonStyle(); - - this._showDesktopButton.connect('button-press-event', () => this._onShowDesktopButtonPress()); - this._showDesktopButton.connect('enter-event', () => { - this._showDesktopButton.add_style_class_name(this._getBackgroundBrightness() ? - 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered'); - - if (SETTINGS.get_boolean('show-showdesktop-hover')) { - this._timeoutsHandler.add([T4, SETTINGS.get_int('show-showdesktop-delay'), () => { - this._hiddenDesktopWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - this._toggleWorkspaceWindows(true, this._hiddenDesktopWorkspace); - }]); - } - }); - - this._showDesktopButton.connect('leave-event', () => { - this._showDesktopButton.remove_style_class_name(this._getBackgroundBrightness() ? - 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered'); - - if (SETTINGS.get_boolean('show-showdesktop-hover')) { - if (this._timeoutsHandler.getId(T4)) { - this._timeoutsHandler.remove(T4); - } else if (this._hiddenDesktopWorkspace) { - this._toggleWorkspaceWindows(false, this._hiddenDesktopWorkspace); - } - } - }); - - this.panel.add_child(this._showDesktopButton); - } else { - if(!this._showDesktopButton) - return; - - this.panel.remove_child(this._showDesktopButton); - this._showDesktopButton.destroy(); - this._showDesktopButton = null; - } - } - - _setShowDesktopButtonStyle() { - let rgb = this._getBackgroundBrightness() ? "rgba(55, 55, 55, .2)" : "rgba(200, 200, 200, .2)"; - - let isLineCustom = SETTINGS.get_boolean('desktop-line-use-custom-color'); - rgb = isLineCustom ? SETTINGS.get_string('desktop-line-custom-color') : rgb; - - if (this._showDesktopButton) { - let buttonSize = SETTINGS.get_int('showdesktop-button-width') + 'px;'; - let isVertical = this.checkIfVertical(); - - let sytle = "border: 0 solid " + rgb + ";"; - sytle += isVertical ? 'border-top-width:1px;height:' + buttonSize : 'border-left-width:1px;width:' + buttonSize; - - this._showDesktopButton.set_style(sytle); - this._showDesktopButton[(isVertical ? 'x' : 'y') + '_expand'] = true; - } - } - - // _getBackgroundBrightness: return true if panel has a bright background color - _getBackgroundBrightness() { - return Utils.checkIfColorIsBright(this.dynamicTransparency.backgroundColorRgb); - } - - _toggleWorkspaceWindows(hide, workspace) { - let time = SETTINGS.get_int('show-showdesktop-time') * .001; - - workspace.list_windows().forEach(w => { - if (!w.minimized && !w.customJS_ding) { - let tweenOpts = { - opacity: hide ? 0 : 255, - time: time, - transition: 'easeOutQuad' - }; - - Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts); - } - }); - } - - _onShowDesktopButtonPress() { - let label = 'trackerFocusApp'; - - this._signalsHandler.removeWithLabel(label); - this._timeoutsHandler.remove(T5); - - if(this._restoreWindowList && this._restoreWindowList.length) { - this._timeoutsHandler.remove(T4); - - let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - let windows = current_workspace.list_windows(); - this._restoreWindowList.forEach(function(w) { - if(windows.indexOf(w) > -1) - Main.activateWindow(w); - }); - this._restoreWindowList = null; - } else { - let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - let windows = current_workspace.list_windows().filter(function (w) { - return w.showing_on_its_workspace() && !w.skip_taskbar; - }); - windows = global.display.sort_windows_by_stacking(windows); - - windows.forEach(function(w) { - w.minimize(); - }); - - this._restoreWindowList = windows; - - this._timeoutsHandler.add([T5, 20, () => this._signalsHandler.addWithLabel( - label, - [ - tracker, - 'notify::focus-app', - () => this._restoreWindowList = null - ] - )]); - } - - Main.overview.hide(); - } - - _onPanelMouseScroll(actor, event) { - let scrollAction = SETTINGS.get_string('scroll-panel-action'); - let direction = Utils.getMouseScrollDirection(event); - - const targetActor = global.stage.get_event_actor(event); - - if (!this._checkIfIgnoredScrollSource(targetActor) && !this._timeoutsHandler.getId(T6)) { - if (direction && scrollAction === 'SWITCH_WORKSPACE') { - let args = [global.display]; - - //adjust for horizontal workspaces - if (Utils.DisplayWrapper.getWorkspaceManager().layout_rows === 1) { - direction = direction == 'up' ? 'left' : 'right'; - } - - //gnome-shell < 3.30 needs an additional "screen" param - global.screen ? args.push(global.screen) : 0; - - let showWsPopup = SETTINGS.get_boolean('scroll-panel-show-ws-popup'); - showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = { display: () => {} }; - Main.wm._showWorkspaceSwitcher.apply(Main.wm, args.concat([0, { get_name: () => 'switch---' + direction }])); - showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = null; - } else if (direction && scrollAction === 'CYCLE_WINDOWS') { - let windows = this.taskbar.getAppInfos().reduce((ws, appInfo) => ws.concat(appInfo.windows), []); - - Utils.activateSiblingWindow(windows, direction); - } else if (scrollAction === 'CHANGE_VOLUME' && !event.is_pointer_emulated()) { - let proto = Volume.OutputIndicator.prototype; - let func = proto._handleScrollEvent || proto.vfunc_scroll_event || proto._onScrollEvent; - let indicator = Main.panel.statusArea[Utils.getSystemMenuInfo().name]._volumeOutput; - - if (indicator.quickSettingsItems) - // new quick settings menu in gnome-shell > 42 - func(indicator.quickSettingsItems[0], event); - else - func.call(indicator, 0, event); - } else { - return; - } - - const scrollDelay = SETTINGS.get_int('scroll-panel-delay'); - - if (scrollDelay) { - this._timeoutsHandler.add([T6, scrollDelay, () => {}]); - } - } - } - - _checkIfIgnoredScrollSource(source) { - let ignoredConstr = ['WorkspaceIndicator']; - - return source.get_parent()._dtpIgnoreScroll || ignoredConstr.indexOf(source.constructor.name) >= 0; - } - - _initProgressManager() { - const progressVisible = SETTINGS.get_boolean('progress-show-bar'); - const countVisible = SETTINGS.get_boolean('progress-show-count'); - const pm = this.progressManager; - - if(!pm && (progressVisible || countVisible)) - this.progressManager = new Progress.ProgressManager(); - else if (pm) - Object.keys(pm._entriesByDBusName).forEach((k) => pm._entriesByDBusName[k].setCountVisible(countVisible)); - } -}); - -export const SecondaryPanel = GObject.registerClass({ -}, class SecondaryPanel extends St.Widget { - - _init(params) { - super._init(params); - } - - vfunc_allocate(box) { - this.set_allocation(box); - } -}); diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelManager.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelManager.js deleted file mode 100755 index b5acf1d..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelManager.js +++ /dev/null @@ -1,771 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * - * Code to re-anchor the panel was taken from Thoma5 BottomPanel: - * https://github.com/Thoma5/gnome-shell-extension-bottompanel - * - * Pattern for moving clock based on Frippery Move Clock by R M Yorston - * http://frippery.org/extensions/ - * - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import * as Overview from './overview.js'; -import * as Panel from './panel.js'; -import * as PanelSettings from './panelSettings.js'; -import * as Proximity from './proximity.js'; -import * as Utils from './utils.js'; -import * as DesktopIconsIntegration from './desktopIconsIntegration.js'; - -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; -import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'; -import {InjectionManager} from 'resource:///org/gnome/shell/extensions/extension.js'; -import {SETTINGS} from './extension.js'; -import {SecondaryMonitorDisplay, WorkspacesView} from 'resource:///org/gnome/shell/ui/workspacesView.js'; - - -export const PanelManager = class { - - constructor() { - this.overview = new Overview.Overview(); - this.panelsElementPositions = {}; - this._injectionManager = new InjectionManager(); - - this._saveMonitors(); - } - - enable(reset) { - let dtpPrimaryIndex = SETTINGS.get_int('primary-monitor'); - - this.allPanels = []; - this.dtpPrimaryMonitor = Main.layoutManager.monitors[dtpPrimaryIndex] || Main.layoutManager.primaryMonitor; - this.proximityManager = new Proximity.ProximityManager(); - - if (this.dtpPrimaryMonitor) { - this.primaryPanel = this._createPanel(this.dtpPrimaryMonitor, SETTINGS.get_boolean('stockgs-keep-top-panel')); - this.allPanels.push(this.primaryPanel); - this.overview.enable(this.primaryPanel); - - this.setFocusedMonitor(this.dtpPrimaryMonitor); - } - - if (SETTINGS.get_boolean('multi-monitors')) { - Main.layoutManager.monitors.filter(m => m != this.dtpPrimaryMonitor).forEach(m => { - this.allPanels.push(this._createPanel(m, true)); - }); - } - - global.dashToPanel.panels = this.allPanels; - global.dashToPanel.emit('panels-created'); - - this.allPanels.forEach(p => { - let panelPosition = p.getPosition(); - let leftOrRight = (panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT); - - p.panelBox.set_size( - leftOrRight ? -1 : p.geom.w + p.geom.lrPadding, - leftOrRight ? p.geom.h + p.geom.tbPadding : -1 - ); - - this._findPanelMenuButtons(p.panelBox).forEach(pmb => this._adjustPanelMenuButton(pmb, p.monitor, panelPosition)); - - p.taskbar.iconAnimator.start(); - }); - - this._setDesktopIconsMargins(); - //in 3.32, BoxPointer now inherits St.Widget - if (BoxPointer.BoxPointer.prototype.vfunc_get_preferred_height) { - let panelManager = this; - - this._injectionManager.overrideMethod(BoxPointer.BoxPointer.prototype, 'vfunc_get_preferred_height', () => function(forWidth) { - let alloc = { min_size: 0, natural_size: 0 }; - - [alloc.min_size, alloc.natural_size] = this.vfunc_get_preferred_height(forWidth); - - return panelManager._getBoxPointerPreferredHeight(this, alloc); - }); - } - - this._updatePanelElementPositions(); - - if (reset) return; - - this._desktopIconsUsableArea = new DesktopIconsIntegration.DesktopIconsUsableAreaClass(); - - this._oldUpdatePanelBarrier = Main.layoutManager._updatePanelBarrier; - Main.layoutManager._updatePanelBarrier = (panel) => { - let panelUpdates = panel ? [panel] : this.allPanels; - - panelUpdates.forEach(p => newUpdatePanelBarrier.call(Main.layoutManager, p)); - }; - Main.layoutManager._updatePanelBarrier(); - - this._oldUpdateHotCorners = Main.layoutManager._updateHotCorners; - Main.layoutManager._updateHotCorners = newUpdateHotCorners.bind(Main.layoutManager); - Main.layoutManager._updateHotCorners(); - - this._forceHotCornerId = SETTINGS.connect('changed::stockgs-force-hotcorner', () => Main.layoutManager._updateHotCorners()); - - if (Main.layoutManager._interfaceSettings) { - this._enableHotCornersId = Main.layoutManager._interfaceSettings.connect('changed::enable-hot-corners', () => Main.layoutManager._updateHotCorners()); - } - - this._oldUpdateWorkspacesViews = Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews; - Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews = this._newUpdateWorkspacesViews.bind(Main.overview._overview._controls._workspacesDisplay); - - this._oldSetPrimaryWorkspaceVisible = Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible - Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible = this._newSetPrimaryWorkspaceVisible.bind(Main.overview._overview._controls._workspacesDisplay); - - LookingGlass.LookingGlass.prototype._oldResize = LookingGlass.LookingGlass.prototype._resize; - LookingGlass.LookingGlass.prototype._resize = _newLookingGlassResize; - - LookingGlass.LookingGlass.prototype._oldOpen = LookingGlass.LookingGlass.prototype.open; - LookingGlass.LookingGlass.prototype.open = _newLookingGlassOpen; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - //listen settings - this._signalsHandler.add( - [ - SETTINGS, - [ - 'changed::primary-monitor', - 'changed::multi-monitors', - 'changed::isolate-monitors', - 'changed::panel-positions', - 'changed::panel-lengths', - 'changed::panel-anchors', - 'changed::stockgs-keep-top-panel' - ], - () => this._reset() - ], - [ - SETTINGS, - 'changed::panel-element-positions', - () => this._updatePanelElementPositions() - ], - [ - SETTINGS, - 'changed::intellihide-key-toggle-text', - () => this._setKeyBindings(true) - ], - [ - SETTINGS, - 'changed::panel-sizes', - () => { - GLib.idle_add(GLib.PRIORITY_LOW, () => { - this._setDesktopIconsMargins(); - return GLib.SOURCE_REMOVE; - }); - } - ], - [ - Utils.DisplayWrapper.getMonitorManager(), - 'monitors-changed', - () => { - if (Main.layoutManager.primaryMonitor) { - this._saveMonitors(); - this._reset(); - } - } - ] - ); - - Panel.panelBoxes.forEach(c => this._signalsHandler.add( - [ - Main.panel[c], - 'actor-added', - (parent, child) => - this.primaryPanel && - this._adjustPanelMenuButton(this._getPanelMenuButton(child), this.primaryPanel.monitor, this.primaryPanel.getPosition()) - ] - )); - - this._setKeyBindings(true); - - // keep GS overview.js from blowing away custom panel styles - if(!SETTINGS.get_boolean('stockgs-keep-top-panel')) - Object.defineProperty(Main.panel, "style", {configurable: true, set(v) {}}); - } - - disable(reset) { - this.primaryPanel && this.overview.disable(); - this.proximityManager.destroy(); - - this.allPanels.forEach(p => { - p.taskbar.iconAnimator.pause(); - - this._findPanelMenuButtons(p.panelBox).forEach(pmb => { - if (pmb.menu._boxPointer._dtpGetPreferredHeightId) { - pmb.menu._boxPointer._container.disconnect(pmb.menu._boxPointer._dtpGetPreferredHeightId); - } - - pmb.menu._boxPointer.sourceActor = pmb.menu._boxPointer._dtpSourceActor; - delete pmb.menu._boxPointer._dtpSourceActor; - pmb.menu._boxPointer._userArrowSide = St.Side.TOP; - }) - - this._removePanelBarriers(p); - - p.disable(); - - let clipContainer = p.panelBox.get_parent(); - - Main.layoutManager._untrackActor(p.panelBox); - Main.layoutManager.removeChrome(clipContainer); - - if (p.isStandalone) { - p.panelBox.destroy(); - } else { - p.panelBox.remove_child(p); - p.remove_child(p.panel); - p.panelBox.add(p.panel); - - p.panelBox.set_position(clipContainer.x, clipContainer.y); - - clipContainer.remove_child(p.panelBox); - Main.layoutManager.addChrome(p.panelBox, { affectsStruts: true, trackFullscreen: true }); - } - }); - - this._injectionManager.clear(); - - if (Main.layoutManager.primaryMonitor) { - Main.layoutManager.panelBox.set_position(Main.layoutManager.primaryMonitor.x, Main.layoutManager.primaryMonitor.y); - Main.layoutManager.panelBox.set_size(Main.layoutManager.primaryMonitor.width, -1); - } - - if (reset) return; - - this._setKeyBindings(false); - - this._signalsHandler.destroy(); - - Main.layoutManager._updateHotCorners = this._oldUpdateHotCorners; - Main.layoutManager._updateHotCorners(); - - SETTINGS.disconnect(this._forceHotCornerId); - - if (this._enableHotCornersId) { - Main.layoutManager._interfaceSettings.disconnect(this._enableHotCornersId); - } - - Main.layoutManager._updatePanelBarrier = this._oldUpdatePanelBarrier; - Main.layoutManager._updatePanelBarrier(); - - Main.overview._overview._controls._workspacesDisplay._updateWorkspacesViews = this._oldUpdateWorkspacesViews; - Main.overview._overview._controls._workspacesDisplay.setPrimaryWorkspaceVisible = this._oldSetPrimaryWorkspaceVisible; - - LookingGlass.LookingGlass.prototype._resize = LookingGlass.LookingGlass.prototype._oldResize; - delete LookingGlass.LookingGlass.prototype._oldResize; - - LookingGlass.LookingGlass.prototype.open = LookingGlass.LookingGlass.prototype._oldOpen; - delete LookingGlass.LookingGlass.prototype._oldOpen - - delete Main.panel.style; - this._desktopIconsUsableArea.destroy(); - this._desktopIconsUsableArea = null; - } - - _setDesktopIconsMargins() { - this._desktopIconsUsableArea?.resetMargins(); - this.allPanels.forEach(p => { - switch(p.geom.position) { - case St.Side.TOP: - this._desktopIconsUsableArea?.setMargins(p.monitor.index, p.geom.h, 0, 0, 0); - break; - case St.Side.BOTTOM: - this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, p.geom.h, 0, 0); - break; - case St.Side.LEFT: - this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, 0, p.geom.w, 0); - break; - case St.Side.RIGHT: - this._desktopIconsUsableArea?.setMargins(p.monitor.index, 0, 0, 0, p.geom.w); - break; - } - }); - } - - setFocusedMonitor(monitor) { - this.focusedMonitorPanel = this.allPanels.find(p => p.monitor == monitor) - - if (!this.checkIfFocusedMonitor(monitor)) { - Main.overview._overview.clear_constraints(); - Main.overview._overview.add_constraint(new Layout.MonitorConstraint({ index: monitor.index })); - - Main.overview._overview._controls._workspacesDisplay._primaryIndex = monitor.index; - } - } - - _newSetPrimaryWorkspaceVisible(visible) { - if (this._primaryVisible === visible) - return; - - this._primaryVisible = visible; - - const primaryIndex = Main.overview._overview._controls._workspacesDisplay._primaryIndex; - const primaryWorkspace = this._workspacesViews[primaryIndex]; - if (primaryWorkspace) - primaryWorkspace.visible = visible; - } - - _newUpdateWorkspacesViews() { - for (let i = 0; i < this._workspacesViews.length; i++) - this._workspacesViews[i].destroy(); - - this._workspacesViews = []; - let monitors = Main.layoutManager.monitors; - for (let i = 0; i < monitors.length; i++) { - let view; - if (i === this._primaryIndex) { - view = new WorkspacesView(i, - this._controls, - this._scrollAdjustment, - this._fitModeAdjustment, - this._overviewAdjustment); - - view.visible = this._primaryVisible; - this.bind_property('opacity', view, 'opacity', GObject.BindingFlags.SYNC_CREATE); - this.add_child(view); - } else { - // No idea why atm, but we need the import at the top of this file and to use the - // full imports ns here, otherwise SecondaryMonitorDisplay can't be used ¯\_(ツ)_/¯ - view = new SecondaryMonitorDisplay(i, - this._controls, - this._scrollAdjustment, - this._fitModeAdjustment, - this._overviewAdjustment); - Main.layoutManager.overviewGroup.add_actor(view); - } - - this._workspacesViews.push(view); - } - } - - _saveMonitors() { - //Mutter meta_monitor_manager_get_primary_monitor (global.display.get_primary_monitor()) doesn't return the same - //monitor as GDK gdk_screen_get_primary_monitor (imports.gi.Gdk.Screen.get_default().get_primary_monitor()). - //Since the Mutter function is what's used in gnome-shell and we can't access it from the settings dialog, store - //the monitors information in a setting so we can use the same monitor indexes as the ones in gnome-shell - let keyMonitors = 'available-monitors'; - let keyPrimary = 'primary-monitor'; - let primaryIndex = Main.layoutManager.primaryIndex; - let newMonitors = [primaryIndex]; - let savedMonitors = SETTINGS.get_value(keyMonitors).deep_unpack(); - let dtpPrimaryIndex = SETTINGS.get_int(keyPrimary); - let newDtpPrimaryIndex = primaryIndex; - - Main.layoutManager.monitors.filter(m => m.index != primaryIndex).forEach(m => newMonitors.push(m.index)); - - if (savedMonitors[0] != dtpPrimaryIndex) { - // dash to panel primary wasn't the gnome-shell primary (first index of available-monitors) - let savedIndex = savedMonitors.indexOf(dtpPrimaryIndex) - - // default to primary if it was set to a monitor that is no longer available - newDtpPrimaryIndex = newMonitors[savedIndex]; - newDtpPrimaryIndex = newDtpPrimaryIndex == null ? primaryIndex : newDtpPrimaryIndex; - } - - SETTINGS.set_int(keyPrimary, newDtpPrimaryIndex); - SETTINGS.set_value(keyMonitors, new GLib.Variant('ai', newMonitors)); - } - - checkIfFocusedMonitor(monitor) { - return Main.overview._overview._controls._workspacesDisplay._primaryIndex == monitor.index; - } - - _createPanel(monitor, isStandalone) { - let panelBox; - let panel; - let clipContainer = new Clutter.Actor(); - - if (isStandalone) { - panelBox = new St.BoxLayout({ name: 'panelBox' }); - } else { - panelBox = Main.layoutManager.panelBox; - Main.layoutManager._untrackActor(panelBox); - panelBox.remove_child(Main.panel); - Main.layoutManager.removeChrome(panelBox); - } - - Main.layoutManager.addChrome(clipContainer, { affectsInputRegion: false }); - clipContainer.add_child(panelBox); - Main.layoutManager.trackChrome(panelBox, { trackFullscreen: true, affectsStruts: true, affectsInputRegion: true }); - - panel = new Panel.Panel(this, monitor, panelBox, isStandalone); - panelBox.add(panel); - panel.enable(); - - panelBox.visible = true; - if (monitor.inFullscreen) { - panelBox.hide(); - } - panelBox.set_position(0, 0); - - return panel; - } - - _reset() { - this.disable(true); - this.allPanels = []; - this.enable(true); - } - - _updatePanelElementPositions() { - this.panelsElementPositions = PanelSettings.getSettingsJson(SETTINGS, 'panel-element-positions'); - this.allPanels.forEach(p => p.updateElementPositions()); - } - - _adjustPanelMenuButton(button, monitor, arrowSide) { - if (button) { - button.menu._boxPointer._dtpSourceActor = button.menu._boxPointer.sourceActor; - button.menu._boxPointer.sourceActor = button; - button.menu._boxPointer._userArrowSide = arrowSide; - button.menu._boxPointer._dtpInPanel = 1; - - if (!button.menu._boxPointer.vfunc_get_preferred_height) { - button.menu._boxPointer._dtpGetPreferredHeightId = button.menu._boxPointer._container.connect('get-preferred-height', (actor, forWidth, alloc) => { - this._getBoxPointerPreferredHeight(button.menu._boxPointer, alloc, monitor); - }); - } - } - } - - _getBoxPointerPreferredHeight(boxPointer, alloc, monitor) { - if (boxPointer._dtpInPanel && boxPointer.sourceActor && SETTINGS.get_boolean('intellihide')) { - monitor = monitor || Main.layoutManager.findMonitorForActor(boxPointer.sourceActor); - let panel = Utils.find(global.dashToPanel.panels, p => p.monitor == monitor); - let excess = alloc.natural_size + panel.dtpSize + 10 - monitor.height; // 10 is arbitrary - - if (excess > 0) { - alloc.natural_size -= excess; - } - } - - return [alloc.min_size, alloc.natural_size]; - } - - _findPanelMenuButtons(container) { - let panelMenuButtons = []; - let panelMenuButton; - - let find = parent => parent.get_children().forEach(c => { - if ((panelMenuButton = this._getPanelMenuButton(c))) { - panelMenuButtons.push(panelMenuButton); - } - - find(c); - }); - - find(container); - - return panelMenuButtons; - } - - _removePanelBarriers(panel) { - if (panel.isStandalone && panel._rightPanelBarrier) { - panel._rightPanelBarrier.destroy(); - } - - if (panel._leftPanelBarrier) { - panel._leftPanelBarrier.destroy(); - delete panel._leftPanelBarrier; - } - } - - _getPanelMenuButton(obj) { - return obj instanceof PanelMenu.Button && obj.menu?._boxPointer ? obj : 0; - } - - _setKeyBindings(enable) { - let keys = { - 'intellihide-key-toggle': () => this.allPanels.forEach(p => p.intellihide.toggle()) - }; - - Object.keys(keys).forEach(k => { - Utils.removeKeybinding(k); - - if (enable) { - Utils.addKeybinding(k, SETTINGS, keys[k], Shell.ActionMode.NORMAL); - } - }); - } - -}; - -// This class drives long-running icon animations, to keep them running in sync -// with each other. -export const IconAnimator = class { - - constructor(actor) { - this._count = 0; - this._started = false; - this._animations = { - dance: [], - }; - this._timeline = new Clutter.Timeline({ - duration: 3000, - repeat_count: -1, - }); - - /* Just use the construction property when no need to support 3.36 */ - if (this._timeline.set_actor) - this._timeline.set_actor(actor); - - this._timeline.connect('new-frame', () => { - const progress = this._timeline.get_progress(); - const danceRotation = progress < 1/6 ? 15*Math.sin(progress*24*Math.PI) : 0; - const dancers = this._animations.dance; - for (let i = 0, iMax = dancers.length; i < iMax; i++) { - dancers[i].target.rotation_angle_z = danceRotation; - } - }); - } - - destroy() { - this._timeline.stop(); - this._timeline = null; - for (let name in this._animations) { - const pairs = this._animations[name]; - for (let i = 0, iMax = pairs.length; i < iMax; i++) { - const pair = pairs[i]; - pair.target.disconnect(pair.targetDestroyId); - } - } - this._animations = null; - } - - pause() { - if (this._started && this._count > 0) { - this._timeline.stop(); - } - this._started = false; - } - - start() { - if (!this._started && this._count > 0) { - this._timeline.start(); - } - this._started = true; - } - - addAnimation(target, name) { - const targetDestroyId = target.connect('destroy', () => this.removeAnimation(target, name)); - this._animations[name].push({ target: target, targetDestroyId: targetDestroyId }); - if (this._started && this._count === 0) { - this._timeline.start(); - } - this._count++; - } - - removeAnimation(target, name) { - const pairs = this._animations[name]; - for (let i = 0, iMax = pairs.length; i < iMax; i++) { - const pair = pairs[i]; - if (pair.target === target) { - target.disconnect(pair.targetDestroyId); - pairs.splice(i, 1); - this._count--; - if (this._started && this._count === 0) { - this._timeline.stop(); - } - return; - } - } - } -}; - -function newUpdateHotCorners() { - // destroy old hot corners - this.hotCorners.forEach(function(corner) { - if (corner) - corner.destroy(); - }); - this.hotCorners = []; - - //global.settings is ubuntu specific setting to disable the hot corner (Tweak tool > Top Bar > Activities Overview Hot Corner) - //this._interfaceSettings is for the setting to disable the hot corner introduced in gnome-shell 3.34 - if ((global.settings.list_keys().indexOf('enable-hot-corners') >= 0 && !global.settings.get_boolean('enable-hot-corners')) || - (this._interfaceSettings && !this._interfaceSettings.get_boolean('enable-hot-corners'))) { - this.emit('hot-corners-changed'); - return; - } - - // build new hot corners - for (let i = 0; i < this.monitors.length; i++) { - let panel = Utils.find(global.dashToPanel.panels, p => p.monitor.index == i); - let panelPosition = panel ? panel.getPosition() : St.Side.BOTTOM; - let panelTopLeft = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT; - let monitor = this.monitors[i]; - let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x; - let cornerY = monitor.y; - - let haveTopLeftCorner = true; - - // If the panel is on the bottom, unless this is explicitly forced, don't add a topleft - // hot corner unless it is actually a top left panel. Otherwise, it stops the mouse - // as you are dragging across. In the future, maybe we will automatically move the - // hotcorner to the bottom when the panel is positioned at the bottom - if (i != this.primaryIndex || (!panelTopLeft && !SETTINGS.get_boolean('stockgs-force-hotcorner'))) { - // Check if we have a top left (right for RTL) corner. - // I.e. if there is no monitor directly above or to the left(right) - let besideX = this._rtl ? monitor.x + 1 : cornerX - 1; - let besideY = cornerY; - let aboveX = cornerX; - let aboveY = cornerY - 1; - - for (let j = 0; j < this.monitors.length; j++) { - if (i == j) - continue; - let otherMonitor = this.monitors[j]; - if (besideX >= otherMonitor.x && - besideX < otherMonitor.x + otherMonitor.width && - besideY >= otherMonitor.y && - besideY < otherMonitor.y + otherMonitor.height) { - haveTopLeftCorner = false; - break; - } - if (aboveX >= otherMonitor.x && - aboveX < otherMonitor.x + otherMonitor.width && - aboveY >= otherMonitor.y && - aboveY < otherMonitor.y + otherMonitor.height) { - haveTopLeftCorner = false; - break; - } - } - } - - if (haveTopLeftCorner) { - let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY); - - corner.setBarrierSize = size => Object.getPrototypeOf(corner).setBarrierSize.call(corner, Math.min(size, 32)); - corner.setBarrierSize(panel ? panel.dtpSize : 32); - this.hotCorners.push(corner); - } else { - this.hotCorners.push(null); - } - } - - this.emit('hot-corners-changed'); -} - -function newUpdatePanelBarrier(panel) { - let barriers = { - _rightPanelBarrier: [(panel.isStandalone ? panel : this)], - _leftPanelBarrier: [panel] - }; - - Object.keys(barriers).forEach(k => { - let obj = barriers[k][0]; - - if (obj[k]) { - obj[k].destroy(); - obj[k] = null; - } - }); - - if (!this.primaryMonitor || !panel.panelBox.height) { - return; - } - - let barrierSize = Math.min(10, panel.panelBox.height); - let fixed1 = panel.monitor.y; - let fixed2 = panel.monitor.y + barrierSize; - - if (panel.checkIfVertical()) { - barriers._rightPanelBarrier.push(panel.monitor.y + panel.monitor.height, Meta.BarrierDirection.NEGATIVE_Y); - barriers._leftPanelBarrier.push(panel.monitor.y, Meta.BarrierDirection.POSITIVE_Y); - } else { - barriers._rightPanelBarrier.push(panel.monitor.x + panel.monitor.width, Meta.BarrierDirection.NEGATIVE_X); - barriers._leftPanelBarrier.push(panel.monitor.x, Meta.BarrierDirection.POSITIVE_X); - } - - switch (panel.getPosition()) { - //values are initialized as St.Side.TOP - case St.Side.BOTTOM: - fixed1 = panel.monitor.y + panel.monitor.height - barrierSize; - fixed2 = panel.monitor.y + panel.monitor.height; - break; - case St.Side.LEFT: - fixed1 = panel.monitor.x + barrierSize; - fixed2 = panel.monitor.x; - break; - case St.Side.RIGHT: - fixed1 = panel.monitor.x + panel.monitor.width - barrierSize; - fixed2 = panel.monitor.x + panel.monitor.width; - break; - } - - //remove left barrier if it overlaps one of the hotcorners - for (let k in this.hotCorners) { - let hc = this.hotCorners[k]; - - if (hc && hc._monitor == panel.monitor && - ((fixed1 == hc._x || fixed2 == hc._x) || fixed1 == hc._y || fixed2 == hc._y)) { - delete barriers._leftPanelBarrier; - break; - } - } - - Object.keys(barriers).forEach(k => { - let barrierOptions = { - display: global.display, - directions: barriers[k][2] - }; - - barrierOptions[panel.varCoord.c1] = barrierOptions[panel.varCoord.c2] = barriers[k][1]; - barrierOptions[panel.fixedCoord.c1] = fixed1; - barrierOptions[panel.fixedCoord.c2] = fixed2; - - barriers[k][0][k] = new Meta.Barrier(barrierOptions); - }); -} - -function _newLookingGlassResize() { - let primaryMonitorPanel = Utils.find(global.dashToPanel.panels, p => p.monitor == Main.layoutManager.primaryMonitor); - let topOffset = primaryMonitorPanel.getPosition() == St.Side.TOP ? primaryMonitorPanel.dtpSize + 8 : 32; - - this._oldResize(); - - this._hiddenY = Main.layoutManager.primaryMonitor.y + topOffset - this.height; - this._targetY = this._hiddenY + this.height; - this.y = this._hiddenY; - - this._objInspector.set_position(this.x + Math.floor(this.width * 0.1), this._targetY + Math.floor(this.height * 0.1)); -} - -function _newLookingGlassOpen() { - if (this._open) - return; - - this._resize(); - this._oldOpen(); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelPositions.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelPositions.js deleted file mode 100644 index a970bdd..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelPositions.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -export const SHOW_APPS_BTN = 'showAppsButton'; -export const ACTIVITIES_BTN = 'activitiesButton'; -export const TASKBAR = 'taskbar'; -export const DATE_MENU = 'dateMenu'; -export const SYSTEM_MENU = 'systemMenu'; -export const LEFT_BOX = 'leftBox'; -export const CENTER_BOX = 'centerBox'; -export const RIGHT_BOX = 'rightBox'; -export const DESKTOP_BTN = 'desktopButton'; - -export const STACKED_TL = 'stackedTL'; -export const STACKED_BR = 'stackedBR'; -export const CENTERED = 'centered'; -export const CENTERED_MONITOR = 'centerMonitor'; - -export const TOP = 'TOP'; -export const BOTTOM = 'BOTTOM'; -export const LEFT = 'LEFT'; -export const RIGHT = 'RIGHT'; - -export const START = 'START'; -export const MIDDLE = 'MIDDLE'; -export const END = 'END'; - -export const defaults = [ - { element: SHOW_APPS_BTN, visible: true, position: STACKED_TL }, - { element: ACTIVITIES_BTN, visible: false, position: STACKED_TL }, - { element: LEFT_BOX, visible: true, position: STACKED_TL }, - { element: TASKBAR, visible: true, position: STACKED_TL }, - { element: CENTER_BOX, visible: true, position: STACKED_BR }, - { element: RIGHT_BOX, visible: true, position: STACKED_BR }, - { element: DATE_MENU, visible: true, position: STACKED_BR }, - { element: SYSTEM_MENU, visible: true, position: STACKED_BR }, - { element: DESKTOP_BTN, visible: true, position: STACKED_BR }, -]; - -export const optionDialogFunctions = {}; - -optionDialogFunctions[SHOW_APPS_BTN] = '_showShowAppsButtonOptions'; -optionDialogFunctions[DESKTOP_BTN] = '_showDesktopButtonOptions'; - -export function checkIfCentered(position) { - return position == CENTERED || position == CENTERED_MONITOR; -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelSettings.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelSettings.js deleted file mode 100644 index fc2d60c..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelSettings.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -import * as Pos from './panelPositions.js'; - -/** Return object representing a settings value that is stored as JSON. */ -export function getSettingsJson(settings, setting) { - try { - return JSON.parse(settings.get_string(setting)); - } catch(e) { - log('Error parsing positions: ' + e.message); - } -} -/** Write value object as JSON to setting in settings. */ -export function setSettingsJson(settings, setting, value) { - try { - const json = JSON.stringify(value); - settings.set_string(setting, json); - } catch(e) { - log('Error serializing setting: ' + e.message); - } -} - -/** Returns size of panel on a specific monitor, in pixels. */ -export function getPanelSize(settings, monitorIndex) { - const sizes = getSettingsJson(settings, 'panel-sizes'); - // Pull in deprecated setting if panel-sizes does not have setting for monitor. - const fallbackSize = settings.get_int('panel-size'); - const theDefault = 48; - return sizes[monitorIndex] || fallbackSize || theDefault; -} - -export function setPanelSize(settings, monitorIndex, value) { - if (!(Number.isInteger(value) && value <= 128 && value >= 16)) { - log('Not setting invalid panel size: ' + value); - return; - } - let sizes = getSettingsJson(settings, 'panel-sizes'); - sizes[monitorIndex] = value; - setSettingsJson(settings, 'panel-sizes', sizes); -} - -/** - * Returns length of panel on a specific monitor, as a whole number percent, - * from settings. e.g. 100 - */ -export function getPanelLength(settings, monitorIndex) { - const lengths = getSettingsJson(settings, 'panel-lengths'); - const theDefault = 100; - return lengths[monitorIndex] || theDefault; -} - -export function setPanelLength(settings, monitorIndex, value) { - if (!(Number.isInteger(value) && value <= 100 && value >= 0)) { - log('Not setting invalid panel length: ' + value); - return; - } - let lengths = getSettingsJson(settings, 'panel-lengths'); - lengths[monitorIndex] = value; - setSettingsJson(settings, 'panel-lengths', lengths); -} - -/** Returns position of panel on a specific monitor. */ -export function getPanelPosition(settings, monitorIndex) { - const positions = getSettingsJson(settings, 'panel-positions'); - const fallbackPosition = settings.get_string('panel-position'); - const theDefault = Pos.BOTTOM; - return positions[monitorIndex] || fallbackPosition || theDefault; -} - -export function setPanelPosition(settings, monitorIndex, value) { - if (!(value === Pos.TOP || value === Pos.BOTTOM || value === Pos.LEFT - || value === Pos.RIGHT)) { - log('Not setting invalid panel position: ' + value); - return; - } - const positions = getSettingsJson(settings, 'panel-positions'); - positions[monitorIndex] = value; - setSettingsJson(settings, 'panel-positions', positions); -} - -/** Returns anchor location of panel on a specific monitor. */ -export function getPanelAnchor(settings, monitorIndex) { - const anchors = getSettingsJson(settings, 'panel-anchors'); - const theDefault = Pos.MIDDLE; - return anchors[monitorIndex] || theDefault; -} - -export function setPanelAnchor(settings, monitorIndex, value) { - if (!(value === Pos.START || value === Pos.MIDDLE || value === Pos.END)) { - log('Not setting invalid panel anchor: ' + value); - return; - } - const anchors = getSettingsJson(settings, 'panel-anchors'); - anchors[monitorIndex] = value; - setSettingsJson(settings, 'panel-anchors', anchors); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelStyle.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelStyle.js deleted file mode 100644 index e4b1f8e..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/panelStyle.js +++ /dev/null @@ -1,314 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * Credits: - * Ideas for recursing child actors and assigning inline styles - * are based on code from the StatusAreaHorizontalSpacing extension - * https://bitbucket.org/mathematicalcoffee/status-area-horizontal-spacing-gnome-shell-extension - * mathematical.coffee@gmail.com - */ - -import * as Utils from './utils.js'; -import {SETTINGS} from './extension.js'; - - -export const PanelStyle = class { - - enable(panel) { - this.panel = panel; - - this._applyStyles(); - - this._bindSettingsChanges(); - } - - disable() { - for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) { - SETTINGS.disconnect(this._dtpSettingsSignalIds[i]); - } - - this._removeStyles(); - } - - _bindSettingsChanges() { - let configKeys = [ - "tray-size", - "leftbox-size", - "tray-padding", - "leftbox-padding", - "status-icon-padding", - ]; - - this._dtpSettingsSignalIds = []; - - for(let i in configKeys) { - this._dtpSettingsSignalIds.push(SETTINGS.connect('changed::' + configKeys[i], () => { - this._removeStyles(); - this._applyStyles(); - })); - } - } - - _applyStyles() { - this._rightBoxOperations = []; - - let trayPadding = SETTINGS.get_int('tray-padding'); - let isVertical = this.panel.checkIfVertical(); - let paddingStyle = 'padding: ' + (isVertical ? '%dpx 0' : '0 %dpx'); - - if(trayPadding >= 0) { - let operation = {}; - let trayPaddingStyleLine; - - if (isVertical) { - trayPaddingStyleLine = paddingStyle.format(trayPadding); - operation.compareFn = function (actor) { - let parent = actor.get_parent(); - return ((parent && parent.has_style_class_name && (parent.has_style_class_name('panel-button') && !parent.has_style_class_name('clock-display'))) || - (actor.has_style_class_name && actor.has_style_class_name('clock'))); - }; - } else { - trayPaddingStyleLine = '-natural-hpadding: %dpx'.format(trayPadding); - if (trayPadding < 6) { - trayPaddingStyleLine += '; -minimum-hpadding: %dpx'.format(trayPadding); - } - - operation.compareFn = function (actor) { - return (actor.has_style_class_name && actor.has_style_class_name('panel-button')); - }; - } - - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, trayPaddingStyleLine, operationIdx); - this._refreshPanelButton(actor); - }; - this._rightBoxOperations.push(operation); - } - - let statusIconPadding = SETTINGS.get_int('status-icon-padding'); - if(statusIconPadding >= 0) { - let statusIconPaddingStyleLine = paddingStyle.format(statusIconPadding) - let operation = {}; - operation.compareFn = function (actor) { - return (actor.has_style_class_name && actor.has_style_class_name('system-status-icon')); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, statusIconPaddingStyleLine, operationIdx); - }; - this._rightBoxOperations.push(operation); - } - - let trayContentSize = SETTINGS.get_int('tray-size'); - if(trayContentSize > 0) { - let trayIconSizeStyleLine = 'icon-size: %dpx'.format(trayContentSize) - let operation = {}; - operation.compareFn = function (actor) { - return (actor.constructor && actor.constructor.name == 'St_Icon'); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, trayIconSizeStyleLine, operationIdx); - }; - this._rightBoxOperations.push(operation); - - let trayContentSizeStyleLine = 'font-size: %dpx'.format(trayContentSize) - operation = {}; - operation.compareFn = function (actor) { - return (actor.constructor && actor.constructor.name == 'St_Label'); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, trayContentSizeStyleLine, operationIdx); - }; - this._rightBoxOperations.push(operation); - - this._overrideStyle(this.panel._rightBox, trayContentSizeStyleLine, 0); - this._overrideStyle(this.panel._centerBox, trayContentSizeStyleLine, 0); - } - - // center box has been moved next to the right box and will be treated the same - this._centerBoxOperations = this._rightBoxOperations; - - this._leftBoxOperations = []; - - let leftboxPadding = SETTINGS.get_int('leftbox-padding'); - if(leftboxPadding >= 0) { - let leftboxPaddingStyleLine = paddingStyle.format(leftboxPadding); - let operation = {}; - operation.compareFn = function (actor) { - let parent = actor.get_parent(); - return (parent && parent.has_style_class_name && parent.has_style_class_name('panel-button')); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, leftboxPaddingStyleLine, operationIdx); - }; - this._leftBoxOperations.push(operation); - } - - let leftboxContentSize = SETTINGS.get_int('leftbox-size'); - if(leftboxContentSize > 0) { - let leftboxIconSizeStyleLine = 'icon-size: %dpx'.format(leftboxContentSize) - let operation = {}; - operation.compareFn = function (actor) { - return (actor.constructor && actor.constructor.name == 'St_Icon'); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, leftboxIconSizeStyleLine, operationIdx); - }; - this._leftBoxOperations.push(operation); - - let leftboxContentSizeStyleLine = 'font-size: %dpx'.format(leftboxContentSize) - operation = {}; - operation.compareFn = function (actor) { - return (actor.constructor && actor.constructor.name == 'St_Label'); - }; - operation.applyFn = (actor, operationIdx) => { - this._overrideStyle(actor, leftboxContentSizeStyleLine, operationIdx); - }; - this._leftBoxOperations.push(operation); - - this._overrideStyle(this.panel._leftBox, leftboxContentSizeStyleLine, 0); - } - - this._applyStylesRecursively(); - - /* connect signal */ - this._rightBoxActorAddedID = this.panel._rightBox.connect('actor-added', - (container, actor) => { - if(this._rightBoxOperations.length && !this._ignoreAddedChild) - this._recursiveApply(actor, this._rightBoxOperations); - - this._ignoreAddedChild = 0; - } - ); - this._centerBoxActorAddedID = this.panel._centerBox.connect('actor-added', - (container, actor) => { - if(this._centerBoxOperations.length && !this._ignoreAddedChild) - this._recursiveApply(actor, this._centerBoxOperations); - - this._ignoreAddedChild = 0; - } - ); - this._leftBoxActorAddedID = this.panel._leftBox.connect('actor-added', - (container, actor) => { - if(this._leftBoxOperations.length) - this._recursiveApply(actor, this._leftBoxOperations); - } - ); - } - - _removeStyles() { - /* disconnect signal */ - if (this._rightBoxActorAddedID) - this.panel._rightBox.disconnect(this._rightBoxActorAddedID); - if (this._centerBoxActorAddedID) - this.panel._centerBox.disconnect(this._centerBoxActorAddedID); - if (this._leftBoxActorAddedID) - this.panel._leftBox.disconnect(this._leftBoxActorAddedID); - - this._restoreOriginalStyle(this.panel._rightBox); - this._restoreOriginalStyle(this.panel._centerBox); - this._restoreOriginalStyle(this.panel._leftBox); - - this._applyStylesRecursively(true); - } - - _applyStylesRecursively(restore) { - /*recurse actors */ - if(this._rightBoxOperations.length) { - // add the system menu as we move it from the rightbox to the panel to position it independently - let children = this.panel._rightBox.get_children().concat([this.panel.statusArea[Utils.getSystemMenuInfo().name].container]); - for(let i in children) - this._recursiveApply(children[i], this._rightBoxOperations, restore); - } - - if(this._centerBoxOperations.length) { - // add the date menu as we move it from the centerbox to the panel to position it independently - let children = this.panel._centerBox.get_children().concat([this.panel.statusArea.dateMenu.container]); - for(let i in children) - this._recursiveApply(children[i], this._centerBoxOperations, restore); - } - - if(this._leftBoxOperations.length) { - let children = this.panel._leftBox.get_children(); - for(let i in children) - this._recursiveApply(children[i], this._leftBoxOperations, restore); - } - } - - _recursiveApply(actor, operations, restore) { - for(let i in operations) { - let o = operations[i]; - if(o.compareFn(actor)) - if(restore) - o.restoreFn ? o.restoreFn(actor) : this._restoreOriginalStyle(actor); - else - o.applyFn(actor, i); - } - - if(actor.get_children) { - let children = actor.get_children(); - for(let i in children) { - this._recursiveApply(children[i], operations, restore); - } - } - } - - _overrideStyle(actor, styleLine, operationIdx) { - if (actor._dtp_original_inline_style === undefined) { - actor._dtp_original_inline_style = actor.get_style(); - } - - if(actor._dtp_style_overrides === undefined) { - actor._dtp_style_overrides = {}; - } - - actor._dtp_style_overrides[operationIdx] = styleLine; - let newStyleLine = ''; - for(let i in actor._dtp_style_overrides) - newStyleLine += actor._dtp_style_overrides[i] + '; '; - actor.set_style(newStyleLine + (actor._dtp_original_inline_style || '')); - } - - _restoreOriginalStyle(actor) { - if (actor._dtp_original_inline_style !== undefined) { - actor.set_style(actor._dtp_original_inline_style); - delete actor._dtp_original_inline_style; - delete actor._dtp_style_overrides; - } - - if (actor.has_style_class_name('panel-button')) { - this._refreshPanelButton(actor); - } - } - - _refreshPanelButton(actor) { - if (actor.visible) { - //force gnome 3.34+ to refresh (having problem with the -natural-hpadding) - let parent = actor.get_parent(); - let children = parent.get_children(); - let actorIndex = 0; - - if (children.length > 1) { - actorIndex = children.indexOf(actor); - } - - this._ignoreAddedChild = [this.panel._centerBox, this.panel._rightBox].indexOf(parent) >= 0; - - parent.remove_child(actor); - parent.insert_child_at_index(actor, actorIndex); - } - } - -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/prefs.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/prefs.js deleted file mode 100644 index d85d3d4..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/prefs.js +++ /dev/null @@ -1,2336 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg. - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import Gdk from 'gi://Gdk'; - -import * as PanelSettings from './panelSettings.js'; -import * as Pos from './panelPositions.js'; - -import {ExtensionPreferences, gettext as _, ngettext} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const SCALE_UPDATE_TIMEOUT = 500; -const DEFAULT_PANEL_SIZES = [ 128, 96, 64, 48, 32, 24, 16 ]; -const DEFAULT_FONT_SIZES = [ 96, 64, 48, 32, 24, 16, 0 ]; -const DEFAULT_MARGIN_SIZES = [ 32, 24, 16, 12, 8, 4, 0 ]; -const DEFAULT_PADDING_SIZES = [ 32, 24, 16, 12, 8, 4, 0, -1 ]; -// Minimum length could be 0, but a higher value may help prevent confusion about where the panel went. -const LENGTH_MARKS = [ 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 ]; -const MAX_WINDOW_INDICATOR = 4; - -const SCHEMA_PATH = '/org/gnome/shell/extensions/dash-to-panel/'; - -/** - * This function was copied from the activities-config extension - * https://github.com/nls1729/acme-code/tree/master/activities-config - * by Norman L. Smith. - */ -function 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++; - } - if (loop == 0) { - end++; - start = end; - } - } - xx = parseInt(css.slice(start, end)).toString(16); - if (xx.length == 1) - xx = '0' + xx; - rrggbb += xx; - css = css.slice(end); - } - return rrggbb; -} - -function setShortcut(settings, shortcutName) { - let shortcut_text = settings.get_string(shortcutName + '-text'); - let [success, key, mods] = Gtk.accelerator_parse(shortcut_text); - - if (success && Gtk.accelerator_valid(key, mods)) { - let shortcut = Gtk.accelerator_name(key, mods); - settings.set_strv(shortcutName, [shortcut]); - } - else { - settings.set_strv(shortcutName, []); - } -} - -function checkHotkeyPrefix(settings) { - settings.delay(); - - let hotkeyPrefix = settings.get_string('hotkey-prefix-text'); - if (hotkeyPrefix == 'Super') - hotkeyPrefix = ''; - else if (hotkeyPrefix == 'SuperAlt') - hotkeyPrefix = ''; - let [ , , mods] = Gtk.accelerator_parse(hotkeyPrefix); - let [ , , shift_mods] = Gtk.accelerator_parse('' + hotkeyPrefix); - let [ , , ctrl_mods] = Gtk.accelerator_parse('' + hotkeyPrefix); - - let numHotkeys = 10; - for (let i = 1; i <= numHotkeys; i++) { - let number = i; - if (number == 10) - number = 0; - let key = Gdk.keyval_from_name(number.toString()); - let key_kp = Gdk.keyval_from_name('KP_' + number.toString()); - if (Gtk.accelerator_valid(key, mods)) { - let shortcut = Gtk.accelerator_name(key, mods); - let shortcut_kp = Gtk.accelerator_name(key_kp, mods); - - // Setup shortcut strings - settings.set_strv('app-hotkey-' + i, [shortcut]); - settings.set_strv('app-hotkey-kp-' + i, [shortcut_kp]); - - // With - shortcut = Gtk.accelerator_name(key, shift_mods); - shortcut_kp = Gtk.accelerator_name(key_kp, shift_mods); - settings.set_strv('app-shift-hotkey-' + i, [shortcut]); - settings.set_strv('app-shift-hotkey-kp-' + i, [shortcut_kp]); - - // With - shortcut = Gtk.accelerator_name(key, ctrl_mods); - shortcut_kp = Gtk.accelerator_name(key_kp, ctrl_mods); - settings.set_strv('app-ctrl-hotkey-' + i, [shortcut]); - settings.set_strv('app-ctrl-hotkey-kp-' + i, [shortcut_kp]); - } - else { - // Reset default settings for the relevant keys if the - // accelerators are invalid - let keys = ['app-hotkey-' + i, 'app-shift-hotkey-' + i, 'app-ctrl-hotkey-' + i, // Regular numbers - 'app-hotkey-kp-' + i, 'app-shift-hotkey-kp-' + i, 'app-ctrl-hotkey-kp-' + i]; // Key-pad numbers - keys.forEach(function(val) { - settings.set_value(val, settings.get_default_value(val)); - }, this); - } - } - - settings.apply(); -} - -function mergeObjects(main, bck) { - for (const prop in bck) { - if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) { - main[prop] = bck[prop]; - } - } - - return main; -} - -const Preferences = class { - - constructor(window, settings, path) { - // this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.dash-to-panel'); - this._rtl = (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL); - this._builder = new Gtk.Builder(); - this._builder.set_scope(new BuilderScope(this)); - this._settings = settings - this._path = path - - window.set_search_enabled(true); - - // dialogs - this._builder.add_from_file(this._path + '/ui/BoxAnimateAppIconHoverOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxDotOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxShowDesktopOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxDynamicOpacityOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxIntellihideOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxShowApplicationsOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxWindowPreviewOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxGroupAppsOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxMiddleClickOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxOverlayShortcut.ui'); - this._builder.add_from_file(this._path + '/ui/BoxSecondaryMenuOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxScrollPanelOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxScrollIconOptions.ui'); - this._builder.add_from_file(this._path + '/ui/BoxAdvancedOptions.ui'); - - // pages - this._builder.add_from_file(this._path + '/ui/SettingsPosition.ui'); - let pagePosition = this._builder.get_object('position'); - window.add(pagePosition); - - this._builder.add_from_file(this._path + '/ui/SettingsStyle.ui'); - let pageStyle = this._builder.get_object('style'); - window.add(pageStyle); - - this._builder.add_from_file(this._path + '/ui/SettingsBehavior.ui'); - let pageBehavior = this._builder.get_object('behavior'); - window.add(pageBehavior); - - this._builder.add_from_file(this._path + '/ui/SettingsAction.ui'); - let pageAction = this._builder.get_object('action'); - window.add(pageAction); - - this._builder.add_from_file(this._path + '/ui/SettingsFineTune.ui'); - let pageFineTune = this._builder.get_object('finetune'); - window.add(pageFineTune); - - this._builder.add_from_file(this._path + '/ui/SettingsAbout.ui'); - let pageAbout = this._builder.get_object('about'); - window.add(pageAbout); - - let listbox = this._builder.get_object('taskbar_display_listbox'); - let provider = new Gtk.CssProvider(); - provider.load_from_data('list { background-color: transparent; }', -1); - let context = listbox.get_style_context(); - context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - // set the window as notebook, it is being used as parent for dialogs - this.notebook = window; - - // Timeout to delay the update of the settings - this._panel_size_timeout = 0; - this._dot_height_timeout = 0; - this._tray_size_timeout = 0; - this._leftbox_size_timeout = 0; - this._appicon_margin_timeout = 0; - this._appicon_padding_timeout = 0; - this._opacity_timeout = 0; - this._tray_padding_timeout = 0; - this._statusicon_padding_timeout = 0; - this._leftbox_padding_timeout = 0; - this._addFormatValueCallbacks(); - this._bindSettings(); - } - - /** - * Connect signals - */ - _connector(builder, object, signal, handler) { - object.connect(signal, this._SignalHandler[handler].bind(this)); - } - - _updateVerticalRelatedOptions() { - let position = this._getPanelPosition(this._currentMonitorIndex); - let isVertical = position == Pos.LEFT || position == Pos.RIGHT; - let showDesktopWidthLabel = this._builder.get_object('show_showdesktop_width_label'); - - showDesktopWidthLabel.set_title(isVertical ? _('Show Desktop button height (px)') : _('Show Desktop button width (px)')); - - this._displayPanelPositionsForMonitor(this._currentMonitorIndex); - } - - _maybeDisableTopPosition() { - let keepTopPanel = this._settings.get_boolean('stockgs-keep-top-panel'); - let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - let topAvailable = !keepTopPanel || (!monitorSync && this._currentMonitorIndex != this.monitors[0]); - let topRadio = this._builder.get_object('position_top_button'); - - topRadio.set_sensitive(topAvailable); - topRadio.set_tooltip_text(!topAvailable ? _('Unavailable when gnome-shell top panel is present') : ''); - } - - _getPanelPosition(monitorIndex) { - return PanelSettings.getPanelPosition(this._settings, monitorIndex); - } - - _setPanelPosition(position) { - const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; - monitorsToSetFor.forEach(monitorIndex => { - PanelSettings.setPanelPosition(this._settings, monitorIndex, position); - }); - this._setAnchorLabels(this._currentMonitorIndex); - } - - _setPositionRadios(position) { - this._ignorePositionRadios = true; - - switch (position) { - case Pos.BOTTOM: - this._builder.get_object('position_bottom_button').set_active(true); - break; - case Pos.TOP: - this._builder.get_object('position_top_button').set_active(true); - break; - case Pos.LEFT: - this._builder.get_object('position_left_button').set_active(true); - break; - case Pos.RIGHT: - this._builder.get_object('position_right_button').set_active(true); - break; - } - - this._ignorePositionRadios = false; - } - - /** - * Set panel anchor combo labels according to whether the monitor's panel is vertical - * or horizontal, or if all monitors' panels are being configured and they are a mix - * of vertical and horizontal. - */ - _setAnchorLabels(currentMonitorIndex) { - const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - const monitorsToSetFor = monitorSync ? this.monitors : [currentMonitorIndex]; - const allVertical = monitorsToSetFor.every(i => { - const position = PanelSettings.getPanelPosition(this._settings, i); - return position === Pos.LEFT || position === Pos.RIGHT - }); - const allHorizontal = monitorsToSetFor.every(i => { - const position = PanelSettings.getPanelPosition(this._settings, i); - return position === Pos.TOP || position === Pos.BOTTOM; - }); - - const anchor_combo = this._builder.get_object('panel_anchor_combo'); - anchor_combo.remove_all(); - - if (allHorizontal) { - anchor_combo.append(Pos.START, _('Left')); - anchor_combo.append(Pos.MIDDLE, _('Center')); - anchor_combo.append(Pos.END, _('Right')); - } else if (allVertical) { - anchor_combo.append(Pos.START, _('Top')); - anchor_combo.append(Pos.MIDDLE, _('Middle')); - anchor_combo.append(Pos.END, _('Bottom')); - } else { - // Setting for a mix of horizontal and vertical panels on different monitors. - anchor_combo.append(Pos.START, _('Start')); - anchor_combo.append(Pos.MIDDLE, _('Middle')); - anchor_combo.append(Pos.END, _('End')); - } - - // Set combo box after re-populating its options. But only if it's for a single-panel - // configuration, or a multi-panel configuration where they all have the same anchor - // setting. So don't set the combo box if there is a multi-panel configuration with - // different anchor settings. - const someAnchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex); - if (monitorsToSetFor.every(i => - PanelSettings.getPanelAnchor(this._settings, i) === someAnchor)) { - const panel_anchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex); - this._builder.get_object('panel_anchor_combo').set_active_id(panel_anchor); - } - } - - /** - * When a monitor is selected, update the widgets for panel position, size, anchoring, - * and contents so they accurately show the settings for the panel on that monitor. - */ - _updateWidgetSettingsForMonitor(monitorIndex) { - // Update display of panel screen position setting - this._maybeDisableTopPosition(); - const panelPosition = this._getPanelPosition(monitorIndex); - this._setPositionRadios(panelPosition); - - // Update display of thickness, length, and anchor settings - const panel_size_scale = this._builder.get_object('panel_size_scale'); - const size = PanelSettings.getPanelSize(this._settings, monitorIndex); - panel_size_scale.set_value(size); - - const panel_length_scale = this._builder.get_object('panel_length_scale'); - const length = PanelSettings.getPanelLength(this._settings, monitorIndex); - panel_length_scale.set_value(length); - this._setAnchorWidgetSensitivity(length); - - this._setAnchorLabels(monitorIndex); - - // Update display of panel content settings - this._displayPanelPositionsForMonitor(monitorIndex); - } - - /** - * Anchor is only relevant if panel length is less than 100%. Enable or disable - * anchor widget sensitivity accordingly. - */ - _setAnchorWidgetSensitivity(panelLength) { - const isPartialLength = panelLength < 100; - this._builder.get_object('panel_anchor_label').set_sensitive(isPartialLength); - this._builder.get_object('panel_anchor_combo').set_sensitive(isPartialLength); - } - - _displayPanelPositionsForMonitor(monitorIndex) { - let taskbarListBox = this._builder.get_object('taskbar_display_listbox'); - - while(taskbarListBox.get_first_child()) - { - taskbarListBox.remove(taskbarListBox.get_first_child()); - } - - let labels = {}; - let panelPosition = this._getPanelPosition(monitorIndex); - let isVertical = panelPosition == Pos.LEFT || panelPosition == Pos.RIGHT; - let panelElementPositionsSettings = PanelSettings.getSettingsJson(this._settings, 'panel-element-positions'); - let panelElementPositions = panelElementPositionsSettings[monitorIndex] || Pos.defaults; - let updateElementsSettings = () => { - let newPanelElementPositions = []; - let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - let monitors = monitorSync ? this.monitors : [monitorIndex]; - - let child = taskbarListBox.get_first_child(); - while (child != null) - { - newPanelElementPositions.push({ - element: child.id, - visible: child.visibleToggleBtn.get_active(), - position: child.positionCombo.get_active_id() - }); - child = child.get_next_sibling(); - } - - monitors.forEach(m => panelElementPositionsSettings[m] = newPanelElementPositions); - this._settings.set_string('panel-element-positions', JSON.stringify(panelElementPositionsSettings)); - }; - - - labels[Pos.SHOW_APPS_BTN] = _('Show Applications button'); - labels[Pos.ACTIVITIES_BTN] = _('Activities button'); - labels[Pos.TASKBAR] = _('Taskbar'); - labels[Pos.DATE_MENU] = _('Date menu'); - labels[Pos.SYSTEM_MENU] = _('System menu'); - labels[Pos.LEFT_BOX] = _('Left box'); - labels[Pos.CENTER_BOX] = _('Center box'); - labels[Pos.RIGHT_BOX] = _('Right box'); - labels[Pos.DESKTOP_BTN] = _('Desktop button'); - - panelElementPositions.forEach(el => { - let row = new Gtk.ListBoxRow(); - let grid = new Gtk.Grid({ margin_start: 12, margin_end: 12, column_spacing: 8 }); - let upDownGrid = new Gtk.Grid({ column_spacing: 2 }); - let upBtn = new Gtk.Button({ tooltip_text: _('Move up') }); - let upImg = new Gtk.Image({ icon_name: 'go-up-symbolic', pixel_size: 12 }); - let downBtn = new Gtk.Button({ tooltip_text: _('Move down') }); - let downImg = new Gtk.Image({ icon_name: 'go-down-symbolic', pixel_size: 12 }); - let visibleToggleBtn = new Gtk.ToggleButton({ label: _('Visible'), active: el.visible }); - let positionCombo = new Gtk.ComboBoxText({ tooltip_text: _('Select element position') }); - let upDownClickHandler = limit => { - let index = row.get_index(); - - if (index != limit) { - taskbarListBox.remove(row); - taskbarListBox.insert(row, index + (!limit ? -1 : 1)); - updateElementsSettings(); - } - }; - - positionCombo.append(Pos.STACKED_TL, isVertical ? _('Stacked to top') : _('Stacked to left')); - positionCombo.append(Pos.STACKED_BR, isVertical ? _('Stacked to bottom') :_('Stacked to right')); - positionCombo.append(Pos.CENTERED, _('Centered')); - positionCombo.append(Pos.CENTERED_MONITOR, _('Monitor Center')); - positionCombo.set_active_id(el.position); - - upBtn.connect('clicked', () => upDownClickHandler(0)); - downBtn.connect('clicked', () => upDownClickHandler(panelElementPositions.length - 1)); - visibleToggleBtn.connect('toggled', () => updateElementsSettings()); - positionCombo.connect('changed', () => updateElementsSettings()); - - upBtn.set_child(upImg); - downBtn.set_child(downImg); - - upDownGrid.attach(upBtn, 0, 0, 1, 1); - upDownGrid.attach(downBtn, 1, 0, 1, 1); - - grid.attach(upDownGrid, 0, 0, 1, 1); - grid.attach(new Gtk.Label({ label: labels[el.element], xalign: 0, hexpand: true }), 1, 0, 1, 1); - - if (Pos.optionDialogFunctions[el.element]) { - let cogImg = new Gtk.Image({ icon_name: 'emblem-system-symbolic' }); - let optionsBtn = new Gtk.Button({ tooltip_text: _('More options') }); - - optionsBtn.get_style_context().add_class('circular'); - optionsBtn.set_child(cogImg); - grid.attach(optionsBtn, 2, 0, 1, 1); - - optionsBtn.connect('clicked', () => this[Pos.optionDialogFunctions[el.element]]()); - } - - grid.attach(visibleToggleBtn, 3, 0, 1, 1); - grid.attach(positionCombo, 4, 0, 1, 1); - - row.id = el.element; - row.visibleToggleBtn = visibleToggleBtn; - row.positionCombo = positionCombo; - - row.set_child(grid); - taskbarListBox.insert(row, -1); - }); - } - - _createPreferencesDialog(title, content, reset_function = null) { - let dialog; - - dialog = new Gtk.Dialog({ title: title, - transient_for: this.notebook.get_root(), - use_header_bar: true, - modal: true }); - - // GTK+ leaves positive values for application-defined response ids. - // Use +1 for the reset action - if (reset_function != null) - dialog.add_button(_('Reset to defaults'), 1); - - dialog.get_content_area().append(content); - - dialog.connect('response', (dialog, id) => { - if (id == 1) { - // restore default settings - if (reset_function) - reset_function(); - } else { - // remove the settings content so it doesn't get destroyed; - dialog.get_content_area().remove(content); - dialog.destroy(); - } - return; - }); - - return dialog; - } - - _showShowAppsButtonOptions() { - let box = this._builder.get_object('show_applications_options'); - - let dialog = this._createPreferencesDialog(_('Show Applications options'), box, () => - { - // restore default settings - this._settings.set_value('show-apps-icon-side-padding', this._settings.get_default_value('show-apps-icon-side-padding')); - this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding')); - this._settings.set_value('show-apps-override-escape', this._settings.get_default_value('show-apps-override-escape')); - handleIconChange.call(this, null); - }); - - let fileChooserButton = this._builder.get_object('show_applications_icon_file_filebutton'); - let fileChooser = new Gtk.FileChooserNative({ title: _('Open icon'), transient_for: dialog }); - let fileImage = this._builder.get_object('show_applications_current_icon_image'); - let fileFilter = new Gtk.FileFilter(); - fileFilter.add_pixbuf_formats(); - fileChooser.filter = fileFilter; - - let handleIconChange = function(newIconPath) { - if (newIconPath && GLib.file_test(newIconPath, GLib.FileTest.EXISTS)) { - let file = Gio.File.new_for_path(newIconPath); - let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(file.read(null), 32, 32, true, null); - - fileImage.set_from_pixbuf(pixbuf); - fileChooser.set_file(file); - fileChooserButton.set_label(newIconPath); - } else { - newIconPath = ''; - fileImage.set_from_icon_name('view-app-grid-symbolic'); - let picturesFolder = Gio.File.new_for_path(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES)); - fileChooser.set_file(picturesFolder); - fileChooserButton.set_label("(None)"); - } - - this._settings.set_string('show-apps-icon-file', newIconPath || ''); - }; - - fileChooserButton.connect('clicked', () => { - fileChooser.show(); - }); - - fileChooser.connect('response', widget => handleIconChange.call(this, widget.get_file().get_path())); - handleIconChange.call(this, this._settings.get_string('show-apps-icon-file')); - - // we have to destroy the fileChooser as well - dialog.connect('response', (dialog, id) => { - if (id != 1) { - fileChooser.destroy(); - } - return; - }); - - dialog.show(); - dialog.set_default_size(1, 1); - } - - _showDesktopButtonOptions() { - let box = this._builder.get_object('box_show_showdesktop_options'); - - let dialog = this._createPreferencesDialog(_('Show Desktop options'), box, () => - { - // restore default settings - this._settings.set_value('showdesktop-button-width', this._settings.get_default_value('showdesktop-button-width')); - this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width')); - - this._settings.set_value('desktop-line-use-custom-color', this._settings.get_default_value('desktop-line-use-custom-color')); - - this._settings.set_value('show-showdesktop-hover', this._settings.get_default_value('show-showdesktop-hover')); - - this._settings.set_value('show-showdesktop-delay', this._settings.get_default_value('show-showdesktop-delay')); - this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay')); - - this._settings.set_value('show-showdesktop-time', this._settings.get_default_value('show-showdesktop-time')); - this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time')); - }); - - this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width')); - this._builder.get_object('show_showdesktop_width_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('showdesktop-button-width', widget.get_value()); - }); - - this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay')); - this._builder.get_object('show_showdesktop_delay_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('show-showdesktop-delay', widget.get_value()); - }); - - this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time')); - this._builder.get_object('show_showdesktop_time_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('show-showdesktop-time', widget.get_value()); - }); - - dialog.show(); - dialog.set_default_size(1, 1); - } - - _addFormatValueCallbacks() { - // position - this._builder.get_object('panel_size_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - // style - this._builder.get_object('appicon_margin_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - this._builder.get_object('appicon_padding_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - // fine-tune box1 - this._builder.get_object('tray_size_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - this._builder.get_object('leftbox_size_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - // fine-tune box2 - this._builder.get_object('tray_padding_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - this._builder.get_object('statusicon_padding_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - this._builder.get_object('leftbox_padding_scale') - .set_format_value_func((scale, value) => { - return value + ' px'; - }); - - // animate hovering app icons dialog - this._builder.get_object('animate_appicon_hover_options_duration_scale') - .set_format_value_func((scale, value) => { - return _("%d ms").format(value); - }); - - this._builder.get_object('animate_appicon_hover_options_rotation_scale') - .set_format_value_func((scale, value) => { - return _("%d °").format(value); - }); - - this._builder.get_object('animate_appicon_hover_options_travel_scale') - .set_format_value_func((scale, value) => { - return _("%d %%").format(value); - }); - - this._builder.get_object('animate_appicon_hover_options_zoom_scale') - .set_format_value_func((scale, value) => { - return _("%d %%").format(value); - }); - - this._builder.get_object('animate_appicon_hover_options_convexity_scale') - .set_format_value_func((scale, value) => { - return _("%.1f").format(value); - }); - - this._builder.get_object('animate_appicon_hover_options_extent_scale') - .set_format_value_func((scale, value) => { - return ngettext("%d icon", "%d icons", value).format(value); - }); - } - - _bindSettings() { - // size options - let panel_size_scale = this._builder.get_object('panel_size_scale'); - panel_size_scale.set_range(DEFAULT_PANEL_SIZES[DEFAULT_PANEL_SIZES.length - 1], DEFAULT_PANEL_SIZES[0]); - DEFAULT_PANEL_SIZES.slice(1, -1).forEach(function(val) { - panel_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString()); - }); - - // Correct for rtl languages - if (this._rtl) { - // Flip value position: this is not done automatically - panel_size_scale.set_value_pos(Gtk.PositionType.LEFT); - // I suppose due to a bug, having a more than one mark and one above a value of 100 - // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable - // and then manually inverting it - panel_size_scale.set_flippable(false); - panel_size_scale.set_inverted(true); - } - - // Dots Position option - let dotPosition = this._settings.get_string('dot-position'); - - switch (dotPosition) { - case 'BOTTOM': - this._builder.get_object('dots_bottom_button').set_active(true); - break; - case 'TOP': - this._builder.get_object('dots_top_button').set_active(true); - break; - case 'LEFT': - this._builder.get_object('dots_left_button').set_active(true); - break; - case 'RIGHT': - this._builder.get_object('dots_right_button').set_active(true); - break; - } - - this._builder.get_object('dot_style_focused_combo').set_active_id(this._settings.get_string('dot-style-focused')); - this._builder.get_object('dot_style_focused_combo').connect('changed', (widget) => { - this._settings.set_string('dot-style-focused', widget.get_active_id()); - }); - - this._builder.get_object('dot_style_unfocused_combo').set_active_id(this._settings.get_string('dot-style-unfocused')); - this._builder.get_object('dot_style_unfocused_combo').connect('changed', (widget) => { - this._settings.set_string('dot-style-unfocused', widget.get_active_id()); - }); - - for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { - let idx = i; - this._builder.get_object('dot_color_' + idx + '_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('dot-color-' + idx, hexString); - }); - - this._builder.get_object('dot_color_unfocused_' + idx + '_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('dot-color-unfocused-' + idx, hexString); - }); - } - - this._builder.get_object('dot_color_apply_all_button').connect('clicked', () => { - for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) { - this._settings.set_value('dot-color-' + i, this._settings.get_value('dot-color-1')); - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-' + i)); - this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); - } - }); - - this._builder.get_object('dot_color_unfocused_apply_all_button').connect('clicked', () => { - for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) { - this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_value('dot-color-unfocused-1')); - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); - this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); - } - }); - - this._builder.get_object('focus_highlight_color_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('focus-highlight-color', hexString); - }); - - this._builder.get_object('dot_style_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_dots_options'); - - let dialog = this._createPreferencesDialog(_('Running Indicator Options'), box, () => - { - // restore default settings - this._settings.set_value('dot-color-dominant', this._settings.get_default_value('dot-color-dominant')); - this._settings.set_value('dot-color-override', this._settings.get_default_value('dot-color-override')); - this._settings.set_value('dot-color-unfocused-different', this._settings.get_default_value('dot-color-unfocused-different')); - - this._settings.set_value('focus-highlight-color', this._settings.get_default_value('focus-highlight-color')); - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('focus-highlight-color')); - this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba); - - this._settings.set_value('focus-highlight-opacity', this._settings.get_default_value('focus-highlight-opacity')); - this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity')); - - for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { - this._settings.set_value('dot-color-' + i, this._settings.get_default_value('dot-color-' + i)); - rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-' + i)); - this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); - - this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_default_value('dot-color-unfocused-' + i)); - rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); - this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); - } - - this._settings.set_value('dot-size', this._settings.get_default_value('dot-size')); - this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size')); - - this._settings.set_value('focus-highlight', this._settings.get_default_value('focus-highlight')); - this._settings.set_value('focus-highlight-dominant', this._settings.get_default_value('focus-highlight-dominant')); - }); - - this._settings.bind('dot-color-dominant', - this._builder.get_object('dot_color_dominant_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('dot-color-override', - this._builder.get_object('dot_color_override_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - // when either becomes active, turn the other off - this._builder.get_object('dot_color_dominant_switch').connect('state-set', (widget) => { - if (widget.get_active()) this._settings.set_boolean('dot-color-override', false); - }); - this._builder.get_object('dot_color_override_switch').connect('state-set', (widget) => { - if (widget.get_active()) this._settings.set_boolean('dot-color-dominant', false); - else this._settings.set_boolean('dot-color-unfocused-different', false); - }); - - this._settings.bind('dot-color-unfocused-different', - this._builder.get_object('dot_color_unfocused_different_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('dot-color-override', - this._builder.get_object('grid_dot_color'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('dot-color-override', - this._builder.get_object('dot_color_unfocused_box'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('dot-color-unfocused-different', - this._builder.get_object('grid_dot_color_unfocused'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-' + i)); - this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); - - rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); - this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); - } - - this._settings.bind('focus-highlight', - this._builder.get_object('focus_highlight_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('focus-highlight', - this._builder.get_object('grid_focus_highlight_options'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('focus-highlight-dominant', - this._builder.get_object('focus_highlight_dominant_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('focus-highlight-dominant', - this._builder.get_object('focus_highlight_color_label'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - - this._settings.bind('focus-highlight-dominant', - this._builder.get_object('focus_highlight_color_colorbutton'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - - - (function() { - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('focus-highlight-color')); - this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba); - }).apply(this); - - this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity')); - this._builder.get_object('focus_highlight_opacity_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('focus-highlight-opacity', widget.get_value()); - }); - - this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size')); - this._builder.get_object('dot_size_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('dot-size', widget.get_value()); - }); - - dialog.show(); - dialog.set_default_size(1, 1); - - }); - - //multi-monitor - this.monitors = this._settings.get_value('available-monitors').deep_unpack(); - - let dtpPrimaryMonitorIndex = this.monitors.indexOf(this._settings.get_int('primary-monitor')); - - if (dtpPrimaryMonitorIndex < 0) { - dtpPrimaryMonitorIndex = 0; - } - - this._currentMonitorIndex = this.monitors[dtpPrimaryMonitorIndex]; - - this._settings.connect('changed::panel-positions', () => this._updateVerticalRelatedOptions()); - this._updateVerticalRelatedOptions(); - - for (let i = 0; i < this.monitors.length; ++i) { - //the gnome-shell primary index is the first one in the "available-monitors" setting - let label = !i ? _('Primary monitor') : _('Monitor ') + (i + 1); - - this._builder.get_object('multimon_primary_combo').append_text(label); - this._builder.get_object('taskbar_position_monitor_combo').append_text(label); - } - - this._builder.get_object('multimon_primary_combo').set_active(dtpPrimaryMonitorIndex); - this._builder.get_object('taskbar_position_monitor_combo').set_active(dtpPrimaryMonitorIndex); - - this._settings.bind('panel-element-positions-monitors-sync', - this._builder.get_object('taskbar_position_sync_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('panel-element-positions-monitors-sync', - this._builder.get_object('taskbar_position_monitor_combo'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - - this._settings.connect('changed::panel-element-positions-monitors-sync', () => { - this._maybeDisableTopPosition(); - // The anchor combo box may has different labels for single- or all-monitor configuration. - this._setAnchorLabels(this._currentMonitorIndex); - }); - - this._builder.get_object('multimon_primary_combo').connect('changed', (widget) => { - this._settings.set_int('primary-monitor', this.monitors[widget.get_active()]); - }); - - this._builder.get_object('taskbar_position_monitor_combo').connect('changed', (widget) => { - this._currentMonitorIndex = this.monitors[widget.get_active()]; - this._updateWidgetSettingsForMonitor(this._currentMonitorIndex); - }); - - this._settings.bind('multi-monitors', - this._builder.get_object('multimon_multi_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - if (this.monitors.length === 1) { - this._builder.get_object('multimon_multi_switch').set_sensitive(false); - } - - const panel_length_scale = this._builder.get_object('panel_length_scale'); - panel_length_scale.connect('value-changed', (widget) => { - const value = widget.get_value(); - const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; - monitorsToSetFor.forEach(monitorIndex => { - PanelSettings.setPanelLength(this._settings, monitorIndex, value); - }); - - this._setAnchorWidgetSensitivity(value); - }); - - this._builder.get_object('panel_anchor_combo').connect('changed', (widget) => { - const value = widget.get_active_id(); - // Value can be null while anchor labels are being swapped out - if (value !== null) { - const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); - const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; - monitorsToSetFor.forEach(monitorIndex => { - PanelSettings.setPanelAnchor(this._settings, monitorIndex, value); - }); - } - }); - - this._updateWidgetSettingsForMonitor(this._currentMonitorIndex); - - //dynamic opacity - this._settings.bind('trans-use-custom-bg', - this._builder.get_object('trans_bg_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-bg', - this._builder.get_object('trans_bg_color_colorbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('trans-bg-color')); - this._builder.get_object('trans_bg_color_colorbutton').set_rgba(rgba); - - this._builder.get_object('trans_bg_color_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('trans-bg-color', hexString); - }); - - this._settings.bind('trans-use-custom-opacity', - this._builder.get_object('trans_opacity_override_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-opacity', - this._builder.get_object('trans_opacity_box'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-opacity', - this._builder.get_object('trans_opacity_box2'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('trans_opacity_override_switch').connect('notify::active', (widget) => { - if (!widget.get_active()) - this._builder.get_object('trans_dyn_switch').set_active(false); - }); - - this._builder.get_object('trans_opacity_spinbutton').set_value(this._settings.get_double('trans-panel-opacity') * 100); - this._builder.get_object('trans_opacity_spinbutton').connect('value-changed', (widget) => { - this._settings.set_double('trans-panel-opacity', widget.get_value() * 0.01); - }); - - this._settings.bind('trans-use-dynamic-opacity', - this._builder.get_object('trans_dyn_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-dynamic-opacity', - this._builder.get_object('trans_dyn_options_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-dynamic-behavior', - this._builder.get_object('trans_options_window_type_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-gradient', - this._builder.get_object('trans_gradient_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-gradient', - this._builder.get_object('trans_gradient_box'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('trans-use-custom-gradient', - this._builder.get_object('trans_gradient_box2'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - rgba.parse(this._settings.get_string('trans-gradient-top-color')); - this._builder.get_object('trans_gradient_color1_colorbutton').set_rgba(rgba); - - this._builder.get_object('trans_gradient_color1_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('trans-gradient-top-color', hexString); - }); - - this._builder.get_object('trans_gradient_color1_spinbutton').set_value(this._settings.get_double('trans-gradient-top-opacity') * 100); - this._builder.get_object('trans_gradient_color1_spinbutton').connect('value-changed', (widget) => { - this._settings.set_double('trans-gradient-top-opacity', widget.get_value() * 0.01); - }); - - rgba.parse(this._settings.get_string('trans-gradient-bottom-color')); - this._builder.get_object('trans_gradient_color2_colorbutton').set_rgba(rgba); - - this._builder.get_object('trans_gradient_color2_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('trans-gradient-bottom-color', hexString); - }); - - this._builder.get_object('trans_gradient_color2_spinbutton').set_value(this._settings.get_double('trans-gradient-bottom-opacity') * 100); - this._builder.get_object('trans_gradient_color2_spinbutton').connect('value-changed', (widget) => { - this._settings.set_double('trans-gradient-bottom-opacity', widget.get_value() * 0.01); - }); - - this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); - this._builder.get_object('trans_options_distance_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('trans-dynamic-distance', widget.get_value()); - }); - - this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100); - this._builder.get_object('trans_options_min_opacity_spinbutton').connect('value-changed', (widget) => { - this._settings.set_double('trans-dynamic-anim-target', widget.get_value() * 0.01); - }); - - this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); - this._builder.get_object('trans_options_anim_time_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('trans-dynamic-anim-time', widget.get_value()); - }); - - this._builder.get_object('trans_dyn_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_dynamic_opacity_options'); - - let dialog = this._createPreferencesDialog(_('Dynamic opacity options'), box, () => - { - // restore default settings - this._settings.set_value('trans-dynamic-behavior', this._settings.get_default_value('trans-dynamic-behavior')); - - this._settings.set_value('trans-dynamic-distance', this._settings.get_default_value('trans-dynamic-distance')); - this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); - - this._settings.set_value('trans-dynamic-anim-target', this._settings.get_default_value('trans-dynamic-anim-target')); - this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100); - - this._settings.set_value('trans-dynamic-anim-time', this._settings.get_default_value('trans-dynamic-anim-time')); - this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); - }); - - dialog.show(); - dialog.set_default_size(1, 1); - - }); - - this._settings.bind('desktop-line-use-custom-color', - this._builder.get_object('override_show_desktop_line_color_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('desktop-line-use-custom-color', - this._builder.get_object('override_show_desktop_line_color_colorbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - rgba.parse(this._settings.get_string('desktop-line-custom-color')); - this._builder.get_object('override_show_desktop_line_color_colorbutton').set_rgba(rgba); - this._builder.get_object('override_show_desktop_line_color_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - this._settings.set_string('desktop-line-custom-color', css); - }); - - - this._settings.bind('intellihide', - this._builder.get_object('intellihide_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide', - this._builder.get_object('intellihide_options_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-hide-from-windows', - this._builder.get_object('intellihide_window_hide_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-hide-from-windows', - this._builder.get_object('intellihide_behaviour_options'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-behaviour', - this._builder.get_object('intellihide_behaviour_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-use-pressure', - this._builder.get_object('intellihide_use_pressure_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-use-pressure', - this._builder.get_object('intellihide_use_pressure_options'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-use-pressure', - this._builder.get_object('intellihide_use_pressure_options2'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-show-in-fullscreen', - this._builder.get_object('intellihide_show_in_fullscreen_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('intellihide-only-secondary', - this._builder.get_object('intellihide_only_secondary_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('multi-monitors', - this._builder.get_object('grid_intellihide_only_secondary'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('multimon_multi_switch').connect('notify::active', (widget) => { - if (!widget.get_active()) - this._builder.get_object('intellihide_only_secondary_switch').set_active(false); - }); - - this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); - this._builder.get_object('intellihide_pressure_threshold_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('intellihide-pressure-threshold', widget.get_value()); - }); - - this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); - this._builder.get_object('intellihide_pressure_time_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('intellihide-pressure-time', widget.get_value()); - }); - - this._settings.bind('intellihide-key-toggle-text', - this._builder.get_object('intellihide_toggle_entry'), - 'text', - Gio.SettingsBindFlags.DEFAULT); - this._settings.connect('changed::intellihide-key-toggle-text', () => setShortcut(this._settings, 'intellihide-key-toggle')); - - this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); - this._builder.get_object('intellihide_animation_time_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('intellihide-animation-time', widget.get_value()); - }); - - this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); - this._builder.get_object('intellihide_close_delay_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('intellihide-close-delay', widget.get_value()); - }); - - this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay')); - this._builder.get_object('intellihide_enable_start_delay_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('intellihide-enable-start-delay', widget.get_value()); - }); - - this._builder.get_object('intellihide_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_intellihide_options'); - - let dialog = this._createPreferencesDialog(_('Intellihide options'), box, () => - { - // restore default settings - this._settings.set_value('intellihide-hide-from-windows', this._settings.get_default_value('intellihide-hide-from-windows')); - this._settings.set_value('intellihide-behaviour', this._settings.get_default_value('intellihide-behaviour')); - this._settings.set_value('intellihide-use-pressure', this._settings.get_default_value('intellihide-use-pressure')); - this._settings.set_value('intellihide-show-in-fullscreen', this._settings.get_default_value('intellihide-show-in-fullscreen')); - this._settings.set_value('intellihide-only-secondary', this._settings.get_default_value('intellihide-only-secondary')); - - this._settings.set_value('intellihide-pressure-threshold', this._settings.get_default_value('intellihide-pressure-threshold')); - this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); - - this._settings.set_value('intellihide-pressure-time', this._settings.get_default_value('intellihide-pressure-time')); - this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); - - this._settings.set_value('intellihide-key-toggle-text', this._settings.get_default_value('intellihide-key-toggle-text')); - - this._settings.set_value('intellihide-animation-time', this._settings.get_default_value('intellihide-animation-time')); - this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); - - this._settings.set_value('intellihide-close-delay', this._settings.get_default_value('intellihide-close-delay')); - this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); - - this._settings.set_value('intellihide-enable-start-delay', this._settings.get_default_value('intellihide-enable-start-delay')); - this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay')); - }); - - dialog.show(); - dialog.set_default_size(1, 1); - - }); - - // Behavior panel - - this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding')); - this._builder.get_object('show_applications_side_padding_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('show-apps-icon-side-padding', widget.get_value()); - }); - - this._settings.bind('show-apps-override-escape', - this._builder.get_object('show_applications_esc_key_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-showdesktop-hover', - this._builder.get_object('show_showdesktop_hide_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-showdesktop-hover', - this._builder.get_object('grid_show_showdesktop_hide_options'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-showdesktop-hover', - this._builder.get_object('grid_show_showdesktop_hide_options2'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-window-previews', - this._builder.get_object('show_window_previews_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-window-previews', - this._builder.get_object('show_window_previews_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-tooltip', - this._builder.get_object('show_tooltip_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-favorites', - this._builder.get_object('show_favorite_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-favorites-all-monitors', - this._builder.get_object('multimon_multi_show_favorites_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-favorites', - this._builder.get_object('multimon_multi_show_favorites_switch'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('show-running-apps', - this._builder.get_object('show_runnning_apps_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._setPreviewTitlePosition(); - - this._builder.get_object('grid_preview_title_font_color_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('window-preview-title-font-color', hexString); - }); - - this._builder.get_object('show_window_previews_button').connect('clicked', () => { - let scrolledWindow = this._builder.get_object('box_window_preview_options'); - - let dialog = this._createPreferencesDialog(_('Window preview options'), scrolledWindow, () => - { - // restore default settings - this._settings.set_value('show-window-previews-timeout', this._settings.get_default_value('show-window-previews-timeout')); - this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout')); - - this._settings.set_value('leave-timeout', this._settings.get_default_value('leave-timeout')); - this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout')); - - this._settings.set_value('window-preview-hide-immediate-click', this._settings.get_default_value('window-preview-hide-immediate-click')); - - this._settings.set_value('window-preview-animation-time', this._settings.get_default_value('window-preview-animation-time')); - this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time')); - - this._settings.set_value('preview-use-custom-opacity', this._settings.get_default_value('preview-use-custom-opacity')); - - this._settings.set_value('window-preview-use-custom-icon-size', this._settings.get_default_value('window-preview-use-custom-icon-size')); - - this._settings.set_value('preview-custom-opacity', this._settings.get_default_value('preview-custom-opacity')); - this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity')); - - this._settings.set_value('window-preview-title-position', this._settings.get_default_value('window-preview-title-position')); - this._setPreviewTitlePosition(); - - this._settings.set_value('peek-mode', this._settings.get_default_value('peek-mode')); - this._settings.set_value('window-preview-show-title', this._settings.get_default_value('window-preview-show-title')); - this._settings.set_value('enter-peek-mode-timeout', this._settings.get_default_value('enter-peek-mode-timeout')); - this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout')); - this._settings.set_value('peek-mode-opacity', this._settings.get_default_value('peek-mode-opacity')); - this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity')); - - this._settings.set_value('window-preview-size', this._settings.get_default_value('window-preview-size')); - this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size')); - - this._settings.set_value('window-preview-fixed-x', this._settings.get_default_value('window-preview-fixed-x')); - this._settings.set_value('window-preview-fixed-y', this._settings.get_default_value('window-preview-fixed-y')); - - this._settings.set_value('window-preview-aspect-ratio-x', this._settings.get_default_value('window-preview-aspect-ratio-x')); - this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString()); - - this._settings.set_value('window-preview-aspect-ratio-y', this._settings.get_default_value('window-preview-aspect-ratio-y')); - this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString()); - - this._settings.set_value('window-preview-padding', this._settings.get_default_value('window-preview-padding')); - this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding')); - - this._settings.set_value('preview-middle-click-close', this._settings.get_default_value('preview-middle-click-close')); - - this._settings.set_value('window-preview-title-font-size', this._settings.get_default_value('window-preview-title-font-size')); - this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size')); - - this._settings.set_value('window-preview-custom-icon-size', this._settings.get_default_value('window-preview-custom-icon-size')); - this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size')); - - this._settings.set_value('window-preview-title-font-weight', this._settings.get_default_value('window-preview-title-font-weight')); - this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight')); - - this._settings.set_value('window-preview-title-font-color', this._settings.get_default_value('window-preview-title-font-color')); - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('window-preview-title-font-color')); - this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba); - }); - - this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout')); - this._builder.get_object('preview_timeout_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('show-window-previews-timeout', widget.get_value()); - }); - - this._settings.bind('preview-middle-click-close', - this._builder.get_object('preview_middle_click_close_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('window-preview-fixed-x', - this._builder.get_object('preview_aspect_ratio_x_fixed_togglebutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('window-preview-fixed-y', - this._builder.get_object('preview_aspect_ratio_y_fixed_togglebutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('preview-use-custom-opacity', - this._builder.get_object('preview_custom_opacity_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('preview-use-custom-opacity', - this._builder.get_object('preview_custom_opacity_spinbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-use-custom-icon-size', - this._builder.get_object('preview_custom_icon_size_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-use-custom-icon-size', - this._builder.get_object('preview_custom_icon_size_spinbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity')); - this._builder.get_object('preview_custom_opacity_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('preview-custom-opacity', widget.get_value()); - }); - - this._settings.bind('peek-mode', - this._builder.get_object('peek_mode_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('peek-mode', - this._builder.get_object('grid_enter_peek_mode_timeout'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('peek-mode', - this._builder.get_object('grid_peek_mode_opacity'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('window-preview-show-title', - this._builder.get_object('preview_show_title_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-show-title', - this._builder.get_object('grid_preview_custom_icon_size'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-show-title', - this._builder.get_object('grid_preview_title_size'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-show-title', - this._builder.get_object('grid_preview_title_weight'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('window-preview-show-title', - this._builder.get_object('grid_preview_title_font_color'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout')); - this._builder.get_object('enter_peek_mode_timeout_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('enter-peek-mode-timeout', widget.get_value()); - }); - - this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout')); - this._builder.get_object('leave_timeout_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('leave-timeout', widget.get_value()); - }); - - this._settings.bind('window-preview-hide-immediate-click', - this._builder.get_object('preview_immediate_click_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time')); - this._builder.get_object('animation_time_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('window-preview-animation-time', widget.get_value()); - }); - - this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity')); - this._builder.get_object('peek_mode_opacity_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('peek-mode-opacity', widget.get_value()); - }); - - this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size')); - this._builder.get_object('preview_size_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('window-preview-size', widget.get_value()); - }); - - this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString()); - this._builder.get_object('preview_aspect_ratio_x_combo').connect('changed', (widget) => { - this._settings.set_int('window-preview-aspect-ratio-x', parseInt(widget.get_active_id(), 10)); - }); - - this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString()); - this._builder.get_object('preview_aspect_ratio_y_combo').connect('changed', (widget) => { - this._settings.set_int('window-preview-aspect-ratio-y', parseInt(widget.get_active_id(), 10)); - }); - - this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding')); - this._builder.get_object('preview_padding_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('window-preview-padding', widget.get_value()); - }); - - this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size')); - this._builder.get_object('preview_title_size_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('window-preview-title-font-size', widget.get_value()); - }); - - this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size')); - this._builder.get_object('preview_custom_icon_size_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('window-preview-custom-icon-size', widget.get_value()); - }); - - this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight')); - this._builder.get_object('grid_preview_title_weight_combo').connect('changed', (widget) => { - this._settings.set_string('window-preview-title-font-weight', widget.get_active_id()); - }); - - (function() { - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('window-preview-title-font-color')); - this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba); - }).apply(this); - - dialog.show(); - - }); - - this._settings.bind('isolate-workspaces', - this._builder.get_object('isolate_workspaces_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('isolate-monitors', - this._builder.get_object('multimon_multi_isolate_monitor_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('overview-click-to-exit', - this._builder.get_object('clicktoexit_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('hide-overview-on-startup', - this._builder.get_object('hide_overview_on_startup_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('group-apps', - this._builder.get_object('group_apps_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN); - - this._settings.bind('group-apps', - this._builder.get_object('show_group_apps_options_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN); - - this._settings.bind('progress-show-count', - this._builder.get_object('show_notification_badge_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('group_apps_label_font_color_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('group-apps-label-font-color', hexString); - }); - - this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').connect('color-set', (button) => { - let rgba = button.get_rgba(); - let css = rgba.to_string(); - let hexString = cssHexString(css); - this._settings.set_string('group-apps-label-font-color-minimized', hexString); - }); - - this._settings.bind('group-apps-use-fixed-width', - this._builder.get_object('group_apps_use_fixed_width_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('group-apps-underline-unfocused', - this._builder.get_object('group_apps_underline_unfocused_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('group-apps-use-launchers', - this._builder.get_object('group_apps_use_launchers_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('show_group_apps_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_group_apps_options'); - - let dialog = this._createPreferencesDialog(_('Ungrouped application options'), box, () => - { - // restore default settings - this._settings.set_value('group-apps-label-font-size', this._settings.get_default_value('group-apps-label-font-size')); - this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size')); - - this._settings.set_value('group-apps-label-font-weight', this._settings.get_default_value('group-apps-label-font-weight')); - this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight')); - - this._settings.set_value('group-apps-label-font-color', this._settings.get_default_value('group-apps-label-font-color')); - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('group-apps-label-font-color')); - this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba); - - this._settings.set_value('group-apps-label-font-color-minimized', this._settings.get_default_value('group-apps-label-font-color-minimized')); - let minimizedFontColor = new Gdk.RGBA(); - minimizedFontColor.parse(this._settings.get_string('group-apps-label-font-color-minimized')); - this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(minimizedFontColor); - - this._settings.set_value('group-apps-label-max-width', this._settings.get_default_value('group-apps-label-max-width')); - this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width')); - - this._settings.set_value('group-apps-use-fixed-width', this._settings.get_default_value('group-apps-use-fixed-width')); - this._settings.set_value('group-apps-underline-unfocused', this._settings.get_default_value('group-apps-underline-unfocused')); - this._settings.set_value('group-apps-use-launchers', this._settings.get_default_value('group-apps-use-launchers')); - }); - - this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size')); - this._builder.get_object('group_apps_label_font_size_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('group-apps-label-font-size', widget.get_value()); - }); - - this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight')); - this._builder.get_object('group_apps_label_font_weight_combo').connect('changed', (widget) => { - this._settings.set_string('group-apps-label-font-weight', widget.get_active_id()); - }); - - (function() { - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('group-apps-label-font-color')); - this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba); - }).apply(this); - - (function() { - let rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('group-apps-label-font-color-minimized')); - this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(rgba); - }).apply(this); - - this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width')); - this._builder.get_object('group_apps_label_max_width_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('group-apps-label-max-width', widget.get_value()); - }); - - dialog.show(); - dialog.set_default_size(600, 1); - - }); - - this._builder.get_object('click_action_combo').set_active_id(this._settings.get_string('click-action')); - this._builder.get_object('click_action_combo').connect('changed', (widget) => { - this._settings.set_string('click-action', widget.get_active_id()); - }); - - this._builder.get_object('shift_click_action_combo').connect('changed', (widget) => { - this._settings.set_string('shift-click-action', widget.get_active_id()); - }); - - this._builder.get_object('middle_click_action_combo').connect('changed', (widget) => { - this._settings.set_string('middle-click-action', widget.get_active_id()); - }); - this._builder.get_object('shift_middle_click_action_combo').connect('changed', (widget) => { - this._settings.set_string('shift-middle-click-action', widget.get_active_id()); - }); - - // Create dialog for middle-click options - this._builder.get_object('middle_click_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_middle_click_options'); - - let dialog = this._createPreferencesDialog(_('Customize middle-click behavior'), box, () => - { - // restore default settings for the relevant keys - let keys = ['shift-click-action', 'middle-click-action', 'shift-middle-click-action']; - keys.forEach(function(val) { - this._settings.set_value(val, this._settings.get_default_value(val)); - }, this); - this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action')); - this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action')); - this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action')); - }); - - this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action')); - - this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action')); - - this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action')); - - this._settings.bind('shift-click-action', - this._builder.get_object('shift_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('middle-click-action', - this._builder.get_object('middle_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('shift-middle-click-action', - this._builder.get_object('shift_middle_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - dialog.show(); - dialog.set_default_size(700, 1); - - }); - - this._builder.get_object('scroll_panel_combo').set_active_id(this._settings.get_string('scroll-panel-action')); - this._builder.get_object('scroll_panel_combo').connect('changed', (widget) => { - this._settings.set_string('scroll-panel-action', widget.get_active_id()); - }); - - this._builder.get_object('scroll_icon_combo').set_active_id(this._settings.get_string('scroll-icon-action')); - this._builder.get_object('scroll_icon_combo').connect('changed', (widget) => { - this._settings.set_string('scroll-icon-action', widget.get_active_id()); - }); - - // Create dialog for panel scroll options - this._builder.get_object('scroll_panel_options_button').connect('clicked', () => { - let box = this._builder.get_object('scroll_panel_options_box'); - - let dialog = this._createPreferencesDialog(_('Customize panel scroll behavior'), box, () => - { - // restore default settings - this._settings.set_value('scroll-panel-delay', this._settings.get_default_value('scroll-panel-delay')); - this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay')); - - this._settings.set_value('scroll-panel-show-ws-popup', this._settings.get_default_value('scroll-panel-show-ws-popup')); - }); - - this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay')); - this._builder.get_object('scroll_panel_options_delay_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('scroll-panel-delay', widget.get_value()); - }); - - this._settings.bind('scroll-panel-show-ws-popup', - this._builder.get_object('scroll_panel_options_show_ws_popup_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - dialog.show(); - dialog.set_default_size(640, 1); - - }); - - // Create dialog for icon scroll options - this._builder.get_object('scroll_icon_options_button').connect('clicked', () => { - let box = this._builder.get_object('scroll_icon_options_box'); - - let dialog = this._createPreferencesDialog(_('Customize icon scroll behavior'), box, () => - { - // restore default settings - this._settings.set_value('scroll-icon-delay', this._settings.get_default_value('scroll-icon-delay')); - this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay')); - }); - - this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay')); - this._builder.get_object('scroll_icon_options_delay_spinbutton').connect('value-changed', (widget) => { - this._settings.set_int('scroll-icon-delay', widget.get_value()); - }); - - dialog.show(); - dialog.set_default_size(640, 1); - - }); - - this._settings.bind('hot-keys', - this._builder.get_object('hot_keys_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('hot-keys', - this._builder.get_object('overlay_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('overlay_combo').connect('changed', (widget) => { - this._settings.set_string('hotkeys-overlay-combo', widget.get_active_id()); - }); - - this._settings.bind('shortcut-previews', - this._builder.get_object('shortcut_preview_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('shortcut_num_keys_combo').set_active_id(this._settings.get_string('shortcut-num-keys')); - this._builder.get_object('shortcut_num_keys_combo').connect('changed', (widget) => { - this._settings.set_string('shortcut-num-keys', widget.get_active_id()); - }); - - this._settings.connect('changed::hotkey-prefix-text', () => {checkHotkeyPrefix(this._settings);}); - - this._builder.get_object('hotkey_prefix_combo').set_active_id(this._settings.get_string('hotkey-prefix-text')); - - this._settings.bind('hotkey-prefix-text', - this._builder.get_object('hotkey_prefix_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('overlay_combo').set_active_id(this._settings.get_string('hotkeys-overlay-combo')); - - this._settings.bind('hotkeys-overlay-combo', - this._builder.get_object('overlay_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('overlay-timeout', - this._builder.get_object('timeout_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') { - this._builder.get_object('timeout_spinbutton').set_sensitive(false); - } - - this._settings.connect('changed::hotkeys-overlay-combo', () => { - if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') - this._builder.get_object('timeout_spinbutton').set_sensitive(false); - else - this._builder.get_object('timeout_spinbutton').set_sensitive(true); - }); - - this._settings.bind('shortcut-text', - this._builder.get_object('shortcut_entry'), - 'text', - Gio.SettingsBindFlags.DEFAULT); - this._settings.connect('changed::shortcut-text', () => {setShortcut(this._settings, 'shortcut');}); - - // Create dialog for number overlay options - this._builder.get_object('overlay_button').connect('clicked', () => { - let box = this._builder.get_object('box_overlay_shortcut'); - - let dialog = this._createPreferencesDialog(_('Advanced hotkeys options'), box, () => - { - // restore default settings for the relevant keys - let keys = ['hotkey-prefix-text', 'shortcut-text', 'hotkeys-overlay-combo', 'overlay-timeout', 'shortcut-previews']; - keys.forEach(function(val) { - this._settings.set_value(val, this._settings.get_default_value(val)); - }, this); - }); - - dialog.show(); - dialog.set_default_size(600, 1); - - }); - - // setup dialog for secondary menu options - this._builder.get_object('secondarymenu_options_button').connect('clicked', () => { - let box = this._builder.get_object('box_secondarymenu_options'); - - let dialog = this._createPreferencesDialog(_('Secondary Menu Options'), box, () => - { - // restore default settings - this._settings.set_value('secondarymenu-contains-appmenu', this._settings.get_default_value('secondarymenu-contains-appmenu')); - this._settings.set_value('secondarymenu-contains-showdetails', this._settings.get_default_value('secondarymenu-contains-showdetails')); - }); - - // TODO setting secondarymenu-contains-appmenu is not being used anywhere - this._settings.bind('secondarymenu-contains-appmenu', - this._builder.get_object('secondarymenu_appmenu_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('secondarymenu-contains-showdetails', - this._builder.get_object('secondarymenu_showdetails_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - dialog.show(); - dialog.set_default_size(480, 1); - - }); - - // setup dialog for advanced options - this._builder.get_object('button_advanced_options').connect('clicked', () => { - let box = this._builder.get_object('box_advanced_options'); - - let dialog = this._createPreferencesDialog(_('Advanced Options'), box); - - dialog.show(); - dialog.set_default_size(480, 1); - - }); - - // Fine-tune panel - - let sizeScales = [ - {objectName: 'tray_size_scale', valueName: 'tray-size', range: DEFAULT_FONT_SIZES }, - {objectName: 'leftbox_size_scale', valueName: 'leftbox-size', range: DEFAULT_FONT_SIZES }, - {objectName: 'appicon_margin_scale', valueName: 'appicon-margin', range: DEFAULT_MARGIN_SIZES }, - {objectName: 'appicon_padding_scale', valueName: 'appicon-padding', range: DEFAULT_MARGIN_SIZES }, - {objectName: 'tray_padding_scale', valueName: 'tray-padding', range: DEFAULT_PADDING_SIZES }, - {objectName: 'leftbox_padding_scale', valueName: 'leftbox-padding', range: DEFAULT_PADDING_SIZES }, - {objectName: 'statusicon_padding_scale', valueName: 'status-icon-padding', range: DEFAULT_PADDING_SIZES }, - {objectName: 'panel_length_scale', valueName: '', range: LENGTH_MARKS } - ]; - - for(const idx in sizeScales) { - let size_scale = this._builder.get_object(sizeScales[idx].objectName); - let range = sizeScales[idx].range; - size_scale.set_range(range[range.length - 1], range[0]); - let value; - if (sizeScales[idx].objectName === 'panel_length_scale') { - value = PanelSettings.getPanelLength(this._settings, this._currentMonitorIndex); - } else { - value = this._settings.get_int(sizeScales[idx].valueName); - } - size_scale.set_value(value); - // Add marks from range arrays, omitting the first and last values. - range.slice(1, -1).forEach(function(val) { - size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString()); - }); - - // Corrent for rtl languages - if (this._rtl) { - // Flip value position: this is not done automatically - size_scale.set_value_pos(Gtk.PositionType.LEFT); - // I suppose due to a bug, having a more than one mark and one above a value of 100 - // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable - // and then manually inverting it - size_scale.set_flippable(false); - size_scale.set_inverted(true); - } - } - - this._settings.bind('animate-app-switch', - this._builder.get_object('animate_app_switch_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('animate-window-launch', - this._builder.get_object('animate_window_launch_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('animate-appicon-hover', - this._builder.get_object('animate_appicon_hover_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('animate-appicon-hover', - this._builder.get_object('animate_appicon_hover_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - { - this._settings.bind('animate-appicon-hover-animation-type', - this._builder.get_object('animate_appicon_hover_options_type_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - let scales = [ - ['animate_appicon_hover_options_duration_scale', 'animate-appicon-hover-animation-duration', 1], - ['animate_appicon_hover_options_rotation_scale', 'animate-appicon-hover-animation-rotation', 1], - ['animate_appicon_hover_options_travel_scale', 'animate-appicon-hover-animation-travel', 100], - ['animate_appicon_hover_options_zoom_scale', 'animate-appicon-hover-animation-zoom', 100], - ['animate_appicon_hover_options_convexity_scale', 'animate-appicon-hover-animation-convexity', 1], - ['animate_appicon_hover_options_extent_scale', 'animate-appicon-hover-animation-extent', 1], - ]; - - let updateScale = scale => { - let [id, key, factor] = scale; - let type = this._settings.get_string('animate-appicon-hover-animation-type'); - let value = this._settings.get_value(key).deep_unpack()[type]; - let defaultValue = this._settings.get_default_value(key).deep_unpack()[type]; - this._builder.get_object(id).sensitive = defaultValue !== undefined; - this._builder.get_object(id).set_value(value * factor || 0); - this._builder.get_object(id).clear_marks(); - this._builder.get_object(id).add_mark(defaultValue * factor, Gtk.PositionType.TOP, - defaultValue !== undefined ? (defaultValue * factor).toString() : ' '); - }; - - scales.forEach(scale => { - let [id, key, factor] = scale; - this._settings.connect('changed::' + key, () => updateScale(scale)); - this._builder.get_object(id).connect('value-changed', widget => { - let type = this._settings.get_string('animate-appicon-hover-animation-type'); - let variant = this._settings.get_value(key); - let unpacked = variant.deep_unpack(); - if (unpacked[type] != widget.get_value() / factor) { - unpacked[type] = widget.get_value() / factor; - this._settings.set_value(key, new GLib.Variant(variant.get_type_string(), unpacked)); - } - }); - }); - - this._settings.connect('changed::animate-appicon-hover-animation-type', () => scales.forEach(updateScale)); - scales.forEach(updateScale); - } - - this._builder.get_object('animate_appicon_hover_button').connect('clicked', () => { - let box = this._builder.get_object('animate_appicon_hover_options'); - - let dialog = this._createPreferencesDialog(_('App icon animation options'), box, () => - { - // restore default settings - this._settings.set_value('animate-appicon-hover-animation-type', this._settings.get_default_value('animate-appicon-hover-animation-type')); - this._settings.set_value('animate-appicon-hover-animation-duration', this._settings.get_default_value('animate-appicon-hover-animation-duration')); - this._settings.set_value('animate-appicon-hover-animation-rotation', this._settings.get_default_value('animate-appicon-hover-animation-rotation')); - this._settings.set_value('animate-appicon-hover-animation-travel', this._settings.get_default_value('animate-appicon-hover-animation-travel')); - this._settings.set_value('animate-appicon-hover-animation-zoom', this._settings.get_default_value('animate-appicon-hover-animation-zoom')); - this._settings.set_value('animate-appicon-hover-animation-convexity', this._settings.get_default_value('animate-appicon-hover-animation-convexity')); - this._settings.set_value('animate-appicon-hover-animation-extent', this._settings.get_default_value('animate-appicon-hover-animation-extent')); - }); - - dialog.show(); - - }); - - this._settings.bind('stockgs-keep-dash', - this._builder.get_object('stockgs_dash_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('stockgs-keep-top-panel', - this._builder.get_object('stockgs_top_panel_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - - - this._settings.connect('changed::stockgs-keep-top-panel', () => this._maybeDisableTopPosition()); - - this._maybeDisableTopPosition(); - - this._settings.bind('stockgs-panelbtn-click-only', - this._builder.get_object('stockgs_panelbtn_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('stockgs-force-hotcorner', - this._builder.get_object('stockgs_hotcorner_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - // About Panel - - const extension = ExtensionPreferences.lookupByURL(import.meta.url); - const {metadata} = extension; - this._builder.get_object('extension_version').set_label(metadata.version.toString() + (metadata.commit ? ' (' + metadata.commit + ')' : '')); - - this._builder.get_object('importexport_export_button').connect('clicked', widget => { - this._showFileChooser( - _('Export settings'), - { action: Gtk.FileChooserAction.SAVE }, - "Save", - filename => { - let file = Gio.file_new_for_path(filename); - let raw = file.replace(null, false, Gio.FileCreateFlags.NONE, null); - let out = Gio.BufferedOutputStream.new_sized(raw, 4096); - - out.write_all(GLib.spawn_command_line_sync('dconf dump ' + SCHEMA_PATH)[1], null); - out.close(null); - } - ); - }); - - this._builder.get_object('importexport_import_button').connect('clicked', widget => { - this._showFileChooser( - _('Import settings'), - { action: Gtk.FileChooserAction.OPEN }, - "Open", - filename => { - if (filename && GLib.file_test(filename, GLib.FileTest.EXISTS)) { - let settingsFile = Gio.File.new_for_path(filename); - let [ , pid, stdin, stdout, stderr] = - GLib.spawn_async_with_pipes( - null, - ['dconf', 'load', SCHEMA_PATH], - null, - GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, - null - ); - - stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true }); - GLib.close(stdout); - GLib.close(stderr); - - stdin.splice(settingsFile.read(null), Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | Gio.OutputStreamSpliceFlags.CLOSE_TARGET, null); - } - } - ); - }); - - } - - _setPreviewTitlePosition() { - switch (this._settings.get_string('window-preview-title-position')) { - case 'BOTTOM': - this._builder.get_object('preview_title_position_bottom_button').set_active(true); - break; - case 'TOP': - this._builder.get_object('preview_title_position_top_button').set_active(true); - break; - } - } - - _showFileChooser(title, params, acceptBtn, acceptHandler) { - let dialog = new Gtk.FileChooserDialog(mergeObjects({ title: title, transient_for: this.notebook.get_root() }, params)); - - dialog.add_button("Cancel", Gtk.ResponseType.CANCEL); - dialog.add_button(acceptBtn, Gtk.ResponseType.ACCEPT); - - dialog.show(); - - dialog.connect('response', (dialog, id) => { - if (id == Gtk.ResponseType.ACCEPT) - acceptHandler.call(this, dialog.get_file().get_path()); - - dialog.destroy(); - }); - } -} - - -const BuilderScope = GObject.registerClass({ - Implements: [Gtk.BuilderScope], -}, class BuilderScope extends GObject.Object { - - _init(preferences) { - this._preferences = preferences; - super._init(); - } - - vfunc_create_closure(builder, handlerName, flags, connectObject) { - if (flags & Gtk.BuilderClosureFlags.SWAPPED) - throw new Error('Unsupported template signal flag "swapped"'); - - if (typeof this[handlerName] === 'undefined') - throw new Error(`${handlerName} is undefined`); - - return this[handlerName].bind(connectObject || this); - } - - on_btn_click(connectObject) { - connectObject.set_label("Clicked"); - } - - position_bottom_button_clicked_cb(button) { - if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.BOTTOM); - } - - position_top_button_clicked_cb(button) { - if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.TOP); - } - - position_left_button_clicked_cb(button) { - if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.LEFT); - } - - position_right_button_clicked_cb(button) { - if (!this._preferences._ignorePositionRadios && button.get_active()) this._preferences._setPanelPosition(Pos.RIGHT); - } - - dots_bottom_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('dot-position', "BOTTOM"); - } - - dots_top_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('dot-position', "TOP"); - } - - dots_left_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('dot-position', "LEFT"); - } - - dots_right_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('dot-position', "RIGHT"); - } - - preview_title_position_bottom_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('window-preview-title-position', 'BOTTOM'); - } - - preview_title_position_top_button_toggled_cb(button) { - if (button.get_active()) - this._preferences._settings.set_string('window-preview-title-position', 'TOP'); - } - - panel_size_scale_value_changed_cb(scale) { - // Avoid settings the size continuously - if (this._preferences._panel_size_timeout > 0) - GLib.Source.remove(this._preferences._panel_size_timeout); - - this._preferences._panel_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - const value = scale.get_value(); - const monitorSync = this._preferences._settings.get_boolean('panel-element-positions-monitors-sync'); - const monitorsToSetFor = monitorSync ? this._preferences.monitors : [this._preferences._currentMonitorIndex]; - monitorsToSetFor.forEach(monitorIndex => { - PanelSettings.setPanelSize(this._preferences._settings, monitorIndex, value); - }); - - this._preferences._panel_size_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - tray_size_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._tray_size_timeout > 0) - GLib.Source.remove(this._preferences._tray_size_timeout); - - this._preferences._tray_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('tray-size', scale.get_value()); - this._preferences._tray_size_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - leftbox_size_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._leftbox_size_timeout > 0) - GLib.Source.remove(this._preferences._leftbox_size_timeout); - - this._preferences._leftbox_size_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('leftbox-size', scale.get_value()); - this._preferences._leftbox_size_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - appicon_margin_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._appicon_margin_timeout > 0) - GLib.Source.remove(this._preferences._appicon_margin_timeout); - - this._preferences._appicon_margin_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('appicon-margin', scale.get_value()); - this._preferences._appicon_margin_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - appicon_padding_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._appicon_padding_timeout > 0) - GLib.Source.remove(this._preferences._appicon_padding_timeout); - - this._preferences._appicon_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('appicon-padding', scale.get_value()); - this._preferences._appicon_padding_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - tray_padding_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._tray_padding_timeout > 0) - GLib.Source.remove(this._preferences._tray_padding_timeout); - - this._preferences._tray_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('tray-padding', scale.get_value()); - this._preferences._tray_padding_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - statusicon_padding_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._statusicon_padding_timeout > 0) - GLib.Source.remove(this._preferences._statusicon_padding_timeout); - - this._preferences._statusicon_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('status-icon-padding', scale.get_value()); - this._preferences._statusicon_padding_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - leftbox_padding_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._preferences._leftbox_padding_timeout > 0) - GLib.Source.remove(this._preferences._leftbox_padding_timeout); - - this._preferences._leftbox_padding_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._preferences._settings.set_int('leftbox-padding', scale.get_value()); - this._preferences._leftbox_padding_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } -}); - - -export default class DashToPanelPreferences extends ExtensionPreferences { - fillPreferencesWindow(window) { - window._settings = this.getSettings('org.gnome.shell.extensions.dash-to-panel'); - - // use default width or window - window.set_default_size(0, 740); - - let preferences = new Preferences(window, window._settings, this.path); - } -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/progress.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/progress.js deleted file mode 100644 index 473b19d..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/progress.js +++ /dev/null @@ -1,597 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - */ - -import Cairo from 'cairo'; -import Gio from 'gi://Gio'; -import Clutter from 'gi://Clutter'; -import Pango from 'gi://Pango'; -import St from 'gi://St'; -import * as Utils from './utils.js'; -import {SETTINGS} from './extension.js'; - -import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; - - -export const ProgressManager = class extends EventEmitter { - - constructor() { - super(); - - this._entriesByDBusName = {}; - - this._launcher_entry_dbus_signal_id = - Gio.DBus.session.signal_subscribe(null, // sender - 'com.canonical.Unity.LauncherEntry', // iface - null, // member - null, // path - null, // arg0 - Gio.DBusSignalFlags.NONE, - this._onEntrySignalReceived.bind(this)); - - this._dbus_name_owner_changed_signal_id = - Gio.DBus.session.signal_subscribe('org.freedesktop.DBus', // sender - 'org.freedesktop.DBus', // interface - 'NameOwnerChanged', // member - '/org/freedesktop/DBus', // path - null, // arg0 - Gio.DBusSignalFlags.NONE, - this._onDBusNameOwnerChanged.bind(this)); - - this._acquireUnityDBus(); - } - - destroy() { - if (this._launcher_entry_dbus_signal_id) { - Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id); - } - - if (this._dbus_name_owner_changed_signal_id) { - Gio.DBus.session.signal_unsubscribe(this._dbus_name_owner_changed_signal_id); - } - - this._releaseUnityDBus(); - } - - size() { - return Object.keys(this._entriesByDBusName).length; - } - - lookupByDBusName(dbusName) { - return this._entriesByDBusName.hasOwnProperty(dbusName) ? this._entriesByDBusName[dbusName] : null; - } - - lookupById(appId) { - let ret = []; - for (let dbusName in this._entriesByDBusName) { - let entry = this._entriesByDBusName[dbusName]; - if (entry && entry.appId() == appId) { - ret.push(entry); - } - } - - return ret; - } - - addEntry(entry) { - let existingEntry = this.lookupByDBusName(entry.dbusName()); - if (existingEntry) { - existingEntry.update(entry); - } else { - this._entriesByDBusName[entry.dbusName()] = entry; - this.emit('progress-entry-added', entry); - } - } - - removeEntry(entry) { - delete this._entriesByDBusName[entry.dbusName()] - this.emit('progress-entry-removed', entry); - } - - _acquireUnityDBus() { - if (!this._unity_bus_id) { - Gio.DBus.session.own_name('com.canonical.Unity', - Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null); - } - } - - _releaseUnityDBus() { - if (this._unity_bus_id) { - Gio.DBus.session.unown_name(this._unity_bus_id); - this._unity_bus_id = 0; - } - } - - _onEntrySignalReceived(connection, sender_name, object_path, - interface_name, signal_name, parameters, user_data) { - if (!parameters || !signal_name) - return; - - if (signal_name == 'Update') { - if (!sender_name) { - return; - } - - this._handleUpdateRequest(sender_name, parameters); - } - } - - _onDBusNameOwnerChanged(connection, sender_name, object_path, - interface_name, signal_name, parameters, user_data) { - if (!parameters || !this.size()) - return; - - let [name, before, after] = parameters.deep_unpack(); - - if (!after) { - if (this._entriesByDBusName.hasOwnProperty(before)) { - this.removeEntry(this._entriesByDBusName[before]); - } - } - } - - _handleUpdateRequest(senderName, parameters) { - if (!senderName || !parameters) { - return; - } - - let [appUri, properties] = parameters.deep_unpack(); - let appId = appUri.replace(/(^\w+:|^)\/\//, ''); - let entry = this.lookupByDBusName(senderName); - - if (entry) { - entry.setDBusName(senderName); - entry.update(properties); - } else { - let entry = new AppProgress(senderName, appId, properties); - this.addEntry(entry); - } - } -}; - -export class AppProgress extends EventEmitter { - - constructor(dbusName, appId, properties) { - super(); - - this._dbusName = dbusName; - this._appId = appId; - this._count = 0; - this._countVisible = false; - this._progress = 0.0; - this._progressVisible = false; - this._urgent = false; - this.update(properties); - } - - appId() { - return this._appId; - } - - dbusName() { - return this._dbusName; - } - - count() { - return this._count; - } - - setCount(count) { - if (this._count != count) { - this._count = count; - this.emit('count-changed', this._count); - } - } - - countVisible() { - return this._countVisible; - } - - setCountVisible(countVisible) { - if (this._countVisible != countVisible) { - this._countVisible = countVisible; - this.emit('count-visible-changed', this._countVisible); - } - } - - progress() { - return this._progress; - } - - setProgress(progress) { - if (this._progress != progress) { - this._progress = progress; - this.emit('progress-changed', this._progress); - } - } - - progressVisible() { - return this._progressVisible; - } - - setProgressVisible(progressVisible) { - if (this._progressVisible != progressVisible) { - this._progressVisible = progressVisible; - this.emit('progress-visible-changed', this._progressVisible); - } - } - - urgent() { - return this._urgent; - } - - setUrgent(urgent) { - if (this._urgent != urgent) { - this._urgent = urgent; - this.emit('urgent-changed', this._urgent); - } - } - - setDBusName(dbusName) { - if (this._dbusName != dbusName) { - let oldName = this._dbusName; - this._dbusName = dbusName; - this.emit('dbus-name-changed', oldName); - } - } - - update(other) { - if (other instanceof AppProgress) { - this.setDBusName(other.dbusName()) - this.setCount(other.count()); - this.setCountVisible(other.countVisible()); - this.setProgress(other.progress()); - this.setProgressVisible(other.progressVisible()) - this.setUrgent(other.urgent()); - } else { - for (let property in other) { - if (other.hasOwnProperty(property)) { - if (property == 'count') { - this.setCount(other[property].get_int64()); - } else if (property == 'count-visible') { - this.setCountVisible(SETTINGS.get_boolean('progress-show-count') && other[property].get_boolean()); - } else if (property == 'progress') { - this.setProgress(other[property].get_double()); - } else if (property == 'progress-visible') { - this.setProgressVisible(SETTINGS.get_boolean('progress-show-bar') && other[property].get_boolean()); - } else if (property == 'urgent') { - this.setUrgent(other[property].get_boolean()); - } else { - // Not implemented yet - } - } - } - } - } -} - - -export const ProgressIndicator = class { - - constructor(source, progressManager) { - this._source = source; - this._progressManager = progressManager; - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - this._sourceDestroyId = this._source.connect('destroy', () => { - this._signalsHandler.destroy(); - }); - - this._notificationBadgeLabel = new St.Label({ style_class: 'badge' }); - this._notificationBadgeBin = new St.Bin({ - child: this._notificationBadgeLabel, y: 2, x: 2 - }); - this._notificationBadgeLabel.add_style_class_name('notification-badge'); - this._notificationBadgeCount = 0; - this._notificationBadgeBin.hide(); - - this._source._dtpIconContainer.add_child(this._notificationBadgeBin); - this._source._dtpIconContainer.connect('notify::allocation', this.updateNotificationBadge.bind(this)); - - this._progressManagerEntries = []; - this._progressManager.lookupById(this._source.app.id).forEach( - (entry) => { - this.insertEntry(entry); - } - ); - - this._signalsHandler.add([ - this._progressManager, - 'progress-entry-added', - this._onEntryAdded.bind(this) - ], [ - this._progressManager, - 'progress-entry-removed', - this._onEntryRemoved.bind(this) - ]); - } - - destroy() { - this._source.disconnect(this._sourceDestroyId); - this._signalsHandler.destroy(); - } - - _onEntryAdded(appProgress, entry) { - if (!entry || !entry.appId()) - return; - if (this._source && this._source.app && this._source.app.id == entry.appId()) { - this.insertEntry(entry); - } - } - - _onEntryRemoved(appProgress, entry) { - if (!entry || !entry.appId()) - return; - - if (this._source && this._source.app && this._source.app.id == entry.appId()) { - this.removeEntry(entry); - } - } - - updateNotificationBadge() { - this._source.updateNumberOverlay(this._notificationBadgeBin); - this._notificationBadgeLabel.clutter_text.ellipsize = Pango.EllipsizeMode.MIDDLE; - } - - _notificationBadgeCountToText(count) { - if (count <= 9999) { - return count.toString(); - } else if (count < 1e5) { - let thousands = count / 1e3; - return thousands.toFixed(1).toString() + "k"; - } else if (count < 1e6) { - let thousands = count / 1e3; - return thousands.toFixed(0).toString() + "k"; - } else if (count < 1e8) { - let millions = count / 1e6; - return millions.toFixed(1).toString() + "M"; - } else if (count < 1e9) { - let millions = count / 1e6; - return millions.toFixed(0).toString() + "M"; - } else { - let billions = count / 1e9; - return billions.toFixed(1).toString() + "B"; - } - } - - setNotificationBadge(count) { - this._notificationBadgeCount = count; - let text = this._notificationBadgeCountToText(count); - this._notificationBadgeLabel.set_text(text); - } - - toggleNotificationBadge(activate) { - if (activate && this._notificationBadgeCount > 0) { - this.updateNotificationBadge(); - this._notificationBadgeBin.show(); - } - else - this._notificationBadgeBin.hide(); - } - - _showProgressOverlay() { - if (this._progressOverlayArea) { - this._updateProgressOverlay(); - return; - } - - this._progressOverlayArea = new St.DrawingArea({x_expand: true, y_expand: true}); - this._progressOverlayArea.add_style_class_name('progress-bar'); - this._progressOverlayArea.connect('repaint', () => { - this._drawProgressOverlay(this._progressOverlayArea); - }); - - this._source._iconContainer.add_child(this._progressOverlayArea); - let node = this._progressOverlayArea.get_theme_node(); - - let [hasColor, color] = node.lookup_color('-progress-bar-background', false); - if (hasColor) - this._progressbar_background = color - else - this._progressbar_background = new Clutter.Color({red: 204, green: 204, blue: 204, alpha: 255}); - - [hasColor, color] = node.lookup_color('-progress-bar-border', false); - if (hasColor) - this._progressbar_border = color; - else - this._progressbar_border = new Clutter.Color({red: 230, green: 230, blue: 230, alpha: 255}); - - this._updateProgressOverlay(); - } - - _hideProgressOverlay() { - if (this._progressOverlayArea) - this._progressOverlayArea.destroy(); - - this._progressOverlayArea = null; - this._progressbar_background = null; - this._progressbar_border = null; - } - - _updateProgressOverlay() { - - if (this._progressOverlayArea) { - this._progressOverlayArea.queue_repaint(); - } - } - - _drawProgressOverlay(area) { - let scaleFactor = Utils.getScaleFactor(); - let [surfaceWidth, surfaceHeight] = area.get_surface_size(); - let cr = area.get_context(); - - let iconSize = this._source.icon.iconSize * scaleFactor; - - let x = Math.floor((surfaceWidth - iconSize) / 2); - let y = Math.floor((surfaceHeight - iconSize) / 2); - - let lineWidth = Math.floor(1.0 * scaleFactor); - let padding = Math.floor(iconSize * 0.05); - let width = iconSize - 2.0*padding; - let height = Math.floor(Math.min(18.0*scaleFactor, 0.20*iconSize)); - x += padding; - y += iconSize - height - padding; - - cr.setLineWidth(lineWidth); - - // Draw the outer stroke - let stroke = new Cairo.LinearGradient(0, y, 0, y + height); - let fill = null; - stroke.addColorStopRGBA(0.5, 0.5, 0.5, 0.5, 0.1); - stroke.addColorStopRGBA(0.9, 0.8, 0.8, 0.8, 0.4); - Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); - - // Draw the background - x += lineWidth; - y += lineWidth; - width -= 2.0*lineWidth; - height -= 2.0*lineWidth; - - stroke = Cairo.SolidPattern.createRGBA(0.20, 0.20, 0.20, 0.9); - fill = new Cairo.LinearGradient(0, y, 0, y + height); - fill.addColorStopRGBA(0.4, 0.25, 0.25, 0.25, 1.0); - fill.addColorStopRGBA(0.9, 0.35, 0.35, 0.35, 1.0); - Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); - - // Draw the finished bar - x += lineWidth; - y += lineWidth; - width -= 2.0*lineWidth; - height -= 2.0*lineWidth; - - let finishedWidth = Math.ceil(this._progress * width); - - let bg = this._progressbar_background; - let bd = this._progressbar_border; - - stroke = Cairo.SolidPattern.createRGBA(bd.red/255, bd.green/255, bd.blue/255, bd.alpha/255); - fill = Cairo.SolidPattern.createRGBA(bg.red/255, bg.green/255, bg.blue/255, bg.alpha/255); - - if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) - Utils.drawRoundedLine(cr, x + lineWidth/2.0 + width - finishedWidth, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); - else - Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); - - cr.$dispose(); - } - - setProgress(progress) { - this._progress = Math.min(Math.max(progress, 0.0), 1.0); - this._updateProgressOverlay(); - } - - toggleProgressOverlay(activate) { - if (activate) { - this._showProgressOverlay(); - } - else { - this._hideProgressOverlay(); - } - } - - insertEntry(appProgress) { - if (!appProgress || this._progressManagerEntries.indexOf(appProgress) !== -1) - return; - - this._progressManagerEntries.push(appProgress); - this._selectEntry(appProgress); - } - - removeEntry(appProgress) { - if (!appProgress || this._progressManagerEntries.indexOf(appProgress) == -1) - return; - - this._progressManagerEntries.splice(this._progressManagerEntries.indexOf(appProgress), 1); - - if (this._progressManagerEntries.length > 0) { - this._selectEntry(this._progressManagerEntries[this._progressManagerEntries.length-1]); - } else { - this.setNotificationBadge(0); - this.toggleNotificationBadge(false); - this.setProgress(0); - this.toggleProgressOverlay(false); - this.setUrgent(false); - } - } - - _selectEntry(appProgress) { - if (!appProgress) - return; - - this._signalsHandler.removeWithLabel('progress-entry'); - - this._signalsHandler.addWithLabel('progress-entry', - [ - appProgress, - 'count-changed', - (appProgress, value) => { - this.setNotificationBadge(value); - } - ], [ - appProgress, - 'count-visible-changed', - (appProgress, value) => { - this.toggleNotificationBadge(value); - } - ], [ - appProgress, - 'progress-changed', - (appProgress, value) => { - this.setProgress(value); - } - ], [ - appProgress, - 'progress-visible-changed', - (appProgress, value) => { - this.toggleProgressOverlay(value); - } - ], [ - appProgress, - 'urgent-changed', - (appProgress, value) => { - this.setUrgent(value) - } - ]); - - this.setNotificationBadge(appProgress.count()); - this.toggleNotificationBadge(appProgress.countVisible()); - this.setProgress(appProgress.progress()); - this.toggleProgressOverlay(appProgress.progressVisible()); - - this._isUrgent = false; - } - - setUrgent(urgent) { - const icon = this._source.icon._iconBin; - if (urgent) { - if (!this._isUrgent) { - icon.set_pivot_point(0.5, 0.5); - this._source.iconAnimator.addAnimation(icon, 'dance'); - this._isUrgent = true; - } - } else { - if (this._isUrgent) { - this._source.iconAnimator.removeAnimation(icon, 'dance'); - this._isUrgent = false; - } - icon.rotation_angle_z = 0; - } - } -}; diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/proximity.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/proximity.js deleted file mode 100644 index eff1548..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/proximity.js +++ /dev/null @@ -1,256 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -import Meta from 'gi://Meta'; -import Mtk from 'gi://Mtk'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import * as Utils from './utils.js'; - -//timeout intervals -const MIN_UPDATE_MS = 200; - -//timeout names -const T1 = 'limitUpdateTimeout'; - -export const Mode = { - ALL_WINDOWS: 0, - FOCUSED_WINDOWS: 1, - MAXIMIZED_WINDOWS: 2 -}; - -export class ProximityWatch { - - constructor(actor, monitorIndex, mode, xThreshold, yThreshold, handler) { - this.actor = actor; - this.monitorIndex = monitorIndex - this.overlap = false; - this.mode = mode; - this.threshold = [xThreshold, yThreshold]; - this.handler = handler; - - this._allocationChangedId = actor.connect('notify::allocation', () => this._updateWatchRect()); - - this._updateWatchRect(); - } - - destroy() { - this.actor.disconnect(this._allocationChangedId); - } - - _updateWatchRect() { - let [actorX, actorY] = this.actor.get_position(); - - this.rect = new Mtk.Rectangle({ - x: actorX - this.threshold[0], - y: actorY - this.threshold[1], - width: this.actor.width + this.threshold[0] * 2, - height: this.actor.height + this.threshold[1] * 2 - }); - } -}; - -export const ProximityManager = class { - - constructor() { - this._counter = 1; - this._watches = {}; - this._focusedWindowInfo = null; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._timeoutsHandler = new Utils.TimeoutsHandler(); - - this._bindSignals(); - this._setFocusedWindow(); - } - - createWatch(actor, monitorIndex, mode, xThreshold, yThreshold, handler) { - let watch = new ProximityWatch(actor, monitorIndex, mode, xThreshold, yThreshold, handler); - - this._watches[this._counter] = watch; - this.update(); - - return this._counter++; - } - - removeWatch(id) { - if (this._watches[id]) { - this._watches[id].destroy(); - delete this._watches[id]; - } - } - - update() { - this._queueUpdate(true); - } - - destroy() { - this._signalsHandler.destroy(); - this._timeoutsHandler.destroy(); - this._disconnectFocusedWindow(); - Object.keys(this._watches).forEach(id => this.removeWatch(id)); - } - - _bindSignals() { - this._signalsHandler.add( - [ - global.window_manager, - 'switch-workspace', - () => this._queueUpdate() - ], - [ - Main.overview, - 'hidden', - () => this._queueUpdate() - ], - [ - global.display, - 'notify::focus-window', - () => { - this._setFocusedWindow(); - this._queueUpdate(); - } - ], - [ - global.display, - 'restacked', - () => this._queueUpdate() - ] - ); - } - - _setFocusedWindow() { - this._disconnectFocusedWindow(); - - let focusedWindow = global.display.focus_window; - - if (focusedWindow) { - let focusedWindowInfo = this._getFocusedWindowInfo(focusedWindow); - - if (focusedWindowInfo && this._checkIfHandledWindowType(focusedWindowInfo.metaWindow)) { - focusedWindowInfo.allocationId = focusedWindowInfo.window.connect('notify::allocation', () => this._queueUpdate()); - focusedWindowInfo.destroyId = focusedWindowInfo.window.connect('destroy', () => this._disconnectFocusedWindow(true)); - - this._focusedWindowInfo = focusedWindowInfo; - } - } - } - - _getFocusedWindowInfo(focusedWindow) { - let window = focusedWindow.get_compositor_private(); - let focusedWindowInfo; - - if (window) { - focusedWindowInfo = { window: window }; - focusedWindowInfo.metaWindow = focusedWindow; - - if (focusedWindow.is_attached_dialog()) { - let mainMetaWindow = focusedWindow.get_transient_for(); - - if (focusedWindowInfo.metaWindow.get_frame_rect().height < mainMetaWindow.get_frame_rect().height) { - focusedWindowInfo.window = mainMetaWindow.get_compositor_private(); - focusedWindowInfo.metaWindow = mainMetaWindow; - } - } - } - - return focusedWindowInfo; - } - - _disconnectFocusedWindow(destroy) { - if (this._focusedWindowInfo && !destroy) { - this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.allocationId); - this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.destroyId); - } - - this._focusedWindowInfo = null; - } - - _getHandledWindows() { - return Utils.getCurrentWorkspace() - .list_windows() - .filter(mw => this._checkIfHandledWindow(mw)); - } - - _checkIfHandledWindow(metaWindow) { - return metaWindow && - !metaWindow.minimized && - !metaWindow.customJS_ding && - this._checkIfHandledWindowType(metaWindow); - } - - _checkIfHandledWindowType(metaWindow) { - let metaWindowType = metaWindow.get_window_type(); - - //https://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/Meta.WindowType.html - return metaWindowType <= Meta.WindowType.SPLASHSCREEN && - metaWindowType != Meta.WindowType.DESKTOP; - } - - _queueUpdate(noDelay) { - if (!noDelay && this._timeoutsHandler.getId(T1)) { - //limit the number of updates - this._pendingUpdate = true; - return; - } - - this._timeoutsHandler.add([T1, MIN_UPDATE_MS, () => this._endLimitUpdate()]); - - let metaWindows = this._getHandledWindows(); - - Object.keys(this._watches).forEach(id => { - let watch = this._watches[id]; - let overlap = !!this._update(watch, metaWindows); - - if (overlap !== watch.overlap) { - watch.handler(overlap); - watch.overlap = overlap; - } - }); - } - - _endLimitUpdate() { - if (this._pendingUpdate) { - this._pendingUpdate = false; - this._queueUpdate(); - } - } - - _update(watch, metaWindows) { - if (watch.mode === Mode.FOCUSED_WINDOWS) - return (this._focusedWindowInfo && - this._checkIfHandledWindow(this._focusedWindowInfo.metaWindow) && - this._checkProximity(this._focusedWindowInfo.metaWindow, watch)); - - if (watch.mode === Mode.MAXIMIZED_WINDOWS) - return metaWindows.some(mw => mw.maximized_vertically && mw.maximized_horizontally && - mw.get_monitor() == watch.monitorIndex); - - //Mode.ALL_WINDOWS - return metaWindows.some(mw => this._checkProximity(mw, watch)); - } - - _checkProximity(metaWindow, watch) { - let windowRect = metaWindow.get_frame_rect(); - - return windowRect.overlap(watch.rect) && - ((!watch.threshold[0] && !watch.threshold[1]) || - metaWindow.get_monitor() == watch.monitorIndex || - windowRect.overlap(global.display.get_monitor_geometry(watch.monitorIndex))); - } -}; diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/schemas/gschemas.compiled deleted file mode 100644 index c52eb65ecf6bbba9c909d531aedca6a43bb28e77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17244 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 fJ%yr~#2N3L4TaPH?Q<7fh0fkxt-+3mj`aN(A>& - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'BOTTOM' - Panel position (Deprecated) - Panel is shown on the Bottom or Top of the screen. - - - true - Sync element positions - Sync panel element positions on all monitors. - - - '{}' - Panel positions - Panel positions (JSON). - - - '{}' - Panel element positions - Panel element positions (JSON). - - - '{}' - Percentages of screen edge for panel to span - Length of the panels, in percent (JSON). - - - '{}' - Positions along screen edge - Where to show the panels if it is not the full length of the screen edge (JSON). - - - '{}' - Panel sizes - Sizes of panels, in pixels. - - - 48 - Panel size (Deprecated) - Set the size of the panel. - - - false - Override Show Desktop line color - Replace current Show Desktop button line color - - - "rgba(200,200,200,0.2)" - Custom Show Desktop line color - Custom Show Desktop button line color - - - 'BOTTOM' - Dot position - Running indicators are shown on the Bottom or Top of the screen. - - - 'METRO' - Style of the running indicator (focused) - Style of the running indicator for the icon for the currently focused application - - - 'METRO' - Style of the running indicator (unfocused) - Style of the running indicator for the icon for applications which are not currently focused - - - false - Running indicator dominant color - Whether to use the app icon's dominant color for .app-well-running-dot - - - false - Running indicator color override - Whether to override the theme background color for .app-well-running-dot - - - "#5294e2" - Color of running indicator (1 window) - Customize the color of the running indicator when one window is running for that application - - - "#5294e2" - Color of running indicator (2 windows) - Customize the color of the running indicator when two windows are running for that application - - - "#5294e2" - Color of running indicator (3 windows) - Customize the color of the running indicator when three windows are running for that application - - - "#5294e2" - Color of running indicator (4+ windows) - Customize the color of the running indicator when four or more windows are running for that application - - - false - Unfocused color is different than focused - Whether to apply a 2nd color scheme to the indicator when the app is not focused - - - "#5294e2" - Color of unfocused running indicator (1 window) - Customize the color of the unfocused running indicator when one window is running for that application - - - "#5294e2" - Color of unfocused running indicator (2 windows) - Customize the color of the unfocused running indicator when two windows are running for that application - - - "#5294e2" - Color of unfocused running indicator (3 windows) - Customize the color of the unfocused running indicator when three windows are running for that application - - - "#5294e2" - Color of unfocused running indicator (4+ windows) - Customize the color of the unfocused running indicator when four or more windows are running for that application - - - 3 - Running indicator height - Height of the running indicator line/diameter of window indicator dots - - - true - Highlight icon of focused application - Whether to highlight the background of the currently focused application's icon - - - false - Highlight icon dominant color - Base the active window highlight color on that application's icon - - - "#EEEEEE" - Color of highlight of focused application - Customize the color of the highlight of the focused application - - - 25 - Opacity of highlight of focused application - Customize the opacity of the highlight of the focused application - - - false - Keep dash - Whether to keep the stock gnome-shell dash while in overview - - - false - Keep top panel - Whether to keep the stock gnome-shell top panel - - - false - Panel menu buttons require click - Whether to activate the panel menu buttons on hover or on click - - - false - Force hot corner - Wheter to force having an Activities hot corner on the primary monitor - - - false - Lock the taskbar - Specifies if the user can modify the taskbar - - - false - Override theme background color - Replace current theme background color for the panel - - - "#000" - Custom background color - Custom background color for the panel - - - false - Custom background color - Replace current theme background color for the panel - - - false - Dynamic opacity - Enable dynamic opacity - - - 0.4 - Panel opacity - Custom opacity for the panel - - - 'ALL_WINDOWS' - Dynamic opacity behavior - Dictates which window type affects the panel opacity - - - 20 - Distance to change opacity - The distance a window needs to be from the panel to change opacity - - - 0.8 - Modified panel opacity - Modified opacity for the panel when a window is near - - - 300 - Opacity change duration - The duration of the animation when the opacity changes - - - false - Custom gradient - Replace current theme gradient for the panel - - - "#000" - Custom gradient top color - Custom gradient top color for the panel - - - 0 - Custom gradient top opacity - Custom gradient top opacity for the panel - - - "#000" - Custom gradient bottom color - Custom gradient bottom color for the panel - - - 0.2 - Custom gradient bottom opacity - Custom gradient bottom opacity for the panel - - - false - Intellihide - Whether to intelligently hide the panel - - - false - Only hide from windows - Dictates if the dash should only hide when in conflict with windows - - - 'FOCUSED_WINDOWS' - Intellihide behaviour - Dictates how to intelligently hide the panel - - - false - Intellihide pressure - To reveal the panel, pressure needs to be applied to the edege of the screen - - - 100 - Intellihide pressure threshold - The pressure needed to reveal the panel - - - 1000 - Intellihide pressure time - The numer of milliseconds that the pressure needs to be applied to reveal the panel - - - false - Intellihide pressure - Allow the panel to be revealed while an application is in fullscreen mode - - - false - Intellihide only secondary - Whether to only hide secondary panels - - - 200 - Intellihide animation time - The animation time (ms) to hide and reveal the panel - - - 400 - Intellihide close delay - The delay (ms) before hiding the panel - - - "<Super>i" - Keybinding toggle intellihide - Keybinding to reveal the panel while in intellihide mode - - - i']]]> - Keybinding toggle intellihide - Keybinding to reveal the panel while in intellihide mode - - - 2000 - Intellihide enable start delay - The delay before enabling intellihide on start - - - "" - Custom Show Applications icon - Customize the Show Applications icon - - - 8 - Show Applications icon side padding - Customize the Show Applications icon side padding - - - true - Override escape key - Override the escape key to return to the desktop when entering the overview using the Show Applications button - - - [] - Show Apps button context menu commands - Commands to add to the Show Apps button right click menu - - - [] - Show Apps button context menu titles - Titles for commands added to Show Apps button right click menu - - - [] - Panel context menu commands - Commands to add to the panel right click menu - - - [] - Panel context menu titles - Titles for commands added to panel right click menu - - - false - Show activities button - Show activities button on the left hand side of the taskbar - - - 8 - Width of show Desktop button - Customize the width of the show Desktop button - - - false - Show desktop on hover - Show the desktop on mouse hover - - - 1000 - Delay show desktop - Delay before showing the desktop - - - 300 - Show desktop animation time - Window fade animation time when showing the destop - - - true - Show window preview - Show preview of running window on hover of app icon - - - true - Show tooltip - Show tooltip on hover of app icon - - - true - Show running apps - Show or hide running application icons in the dash - - - true - Show favorites apps - Show or hide favorite application icons in the dash - - - 400 - Icon enter display time - Amount of time after entering icon to wait before displaying window preview if icon is not clicked or mouse has not left. - - - true - Enable peek mode - Peek a window upon hover for some time - - - true - Display title in preview - Display window title in preview - - - false - Window previews manual styling - This defines if the default window previews styling should be applied - - - 'TOP' - Title position - Position of the window title, close button and icon in preview. - - - "#dddddd" - Window previews title font color - This defines the window preview titles font color. - - - 14 - Window previews title font size - This defines the window preview titles font size. - - - false - Window previews use custom icon size - Window previews use custom application icon size. - - - 16 - Window previews custom icon size - Window previews custom application icon size. - - - 260 - Window previews animation time - This defines the window previews animation time. - - - 'inherit' - Font weight of window preview titles - This defines the font weight of window preview titles. Supported values: inherit (from theme), normal, lighter, bold and bolder. - - - 240 - Window previews size - Preferred window previews size - - - false - Fixed aspect ratio X - This defines if the window previews use a fixed aspect ratio X. - - - true - Fixed aspect ratio Y - This defines if the window previews use a fixed aspect ratio Y. - - - 8 - Window previews padding - The padding of the window previews - - - 16 - Aspect ratio X - The window previews respected aspect ratio X. - - - 9 - Aspect ratio Y - The window previews respected aspect ratio Y. - - - false - Immediate hide on icon click - The window previews immediately hide when an application icon is clicked. - - - false - Provide workspace isolation - Dash shows only windows from the current workspace - - - false - Close overview by clicking in empty space - Close overview or app grid by clicking in empty space - - - false - Hide overview on startup - Hide overview on startup, which would be shown by default at gnome startup. - - - true - Group applications - Dash groups the application instances under the same icon - - - 14 - Application title font size - When the applications are ungrouped, this defines the application titles font size. - - - 'inherit' - Font weight of application titles - When the applications are ungrouped, this defines font weight of application titles. Supported values: inherit (from theme), normal, lighter, bold and bolder. - - - "#dddddd" - Application title font color - When the applications are ungrouped, this defines the application titles font color. - - - "#dddddd" - Minimized application title font color - When the applications are ungrouped, this defines the titles font color for minimized applications. - - - 160 - Application title max width - When the applications are ungrouped, this defines the application titles maximum width. - - - true - Use a fixed width for the application titles - The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width. - - - true - Display running indicators on unfocused applications - When the applications are ungrouped, this defines if running applications should display an indicator. - - - false - Use favorite icons as application launchers - When the applications are ungrouped, this defines if running applications stay separate from the favorite icons. - - - 0 - Primary monitor index - Specifies the index of the primary monitor. - - - true - Display panels on all monitors - Specifies if a panel is shown on every monitors - - - [] - Available monitors - Available gnome-shell (Mutter) monitors, internal use - - - false - Provide monitor isolation - Dash shows only windows from the current monitor - - - true - Display the favorites on all monitors - Specifies if every panel should display the favorite applications. If false, the favorite appplications are only displayed on the primary monitor. - - - true - Customize click behaviour - Customize action on various mouse events - - - true - Minimize on shift+click - - - true - Activate only one window - - - 'CYCLE-MIN' - Action when clicking on a running app - Set the action that is executed when clicking on the icon of a running application - - - 'MINIMIZE' - Action when shift+clicking on a running app - Set the action that is executed when shift+clicking on the icon of a running application - - - 'LAUNCH' - Action when clicking on a running app - Set the action that is executed when middle-clicking on the icon of a running application - - - 'LAUNCH' - Action when clicking on a running app - Set the action that is executed when shift+middle-clicking on the icon of a running application - - - 'SWITCH_WORKSPACE' - Action when scrolling over the panel - Set the action that is executed when scrolling over the panel - - - 0 - Delay between panel mouse scroll events - Set the minimum delay between panel mouse scroll events - - - true - Show the workspace switch head-up when workspace is changed by scrolling on the panel - - - 'CYCLE_WINDOWS' - Action when scrolling over a running app - Set the action that is executed when scrolling over a running application - - - 0 - Delay between icon mouse scroll events - Set the minimum delay between icon mouse scroll events - - - 100 - Icon leave preview timeout - Amount of time to leave preview windows open when the mouse has left the application's icon. - - - 500 - Enter window peeking mode timeout - Amount of time of inactivity to enter the window peeking mode when the mouse has entered a window preview. - - - 40 - Window peeking mode opacity - All windows except for the peeked one have their opacity set to the same value. - - - true - Middle click preview to close window - Middle click on the window preview to close that window - - - true - Window previews use custom opacity - Window previews background use a different opacity from the panel - - - 80 - Window previews background opacity - Window previews use this custom background opacity. - - - 0 - Tray font size - Set the size of the tray font. (0 for default) - - - 0 - Leftbox font size - Set the size of the leftBox font. (0 for default) - - - 8 - App icon margin - Set the margin for application icons in the embedded dash. - - - 4 - App icon padding - Set the padding for application icons in the embedded dash. - - - -1 - Tray item padding - Set the size of the tray padding. (-1 for default) - - - -1 - Leftbox item padding - Set the size of the leftBox padding. (-1 for default) - - - -1 - Status icon padding - Set the size of the aggregate (status) menu icon padding. (-1 for default) - - - true - Animate running indicator when open/closing/switching applications - - - true - Animate when new window launched - - - false - Animate app icon on hover - - - 'SIMPLE' - App icon hover animation type - - - {'RIPPLE':2,'PLANK':1} - App icon hover animation curve convexity (1 is linear, more is convex, less is concave) - - - {'SIMPLE':160,'RIPPLE':130,'PLANK':100} - App icon hover animation duration in milliseconds - - - {'RIPPLE':4,'PLANK':4} - App icon hover animation extent (maximum number of animated icons) - - - {'SIMPLE':0,'RIPPLE':10,'PLANK':0} - App icon hover animation rotation in degrees - - - {'SIMPLE':0.30,'RIPPLE':0.40,'PLANK':0} - App icon hover animation travel translation in relation to the app icon size - - - {'SIMPLE':1,'RIPPLE':1.25,'PLANK':2} - App icon hover animation zoom scale in relation to the app icon size - - - true - Integrate items from the gnome appmenu into the right click menu - - - false - Display Show Details to open Gnome Software from right click menu - - - "<Super>q" - Keybinding to show the dock and the number overlay. - Behavior depends on hotkeys-show-dock and hotkeys-overlay. - - - q']]]> - Keybinding to show the dock and the number overlay. - Behavior depends on hotkeys-show-dock and hotkeys-overlay. - - - 2000 - Timeout to hide the dock, in seconds - Sets the time duration before the dock is hidden again. - - - 750 - Timeout to hide the dock, in seconds - Sets the time duration before the dock is hidden again. - - - 'TEMPORARILY' - Transitivity of the number overlay - You can choose between NEVER, TEMPORARILY and ALWAYS. - - - false - Super Hot-Keys - Launch and switch between dash items using Super+(0-9) - - - 'Super' - Prefix to use for hotkeys - You can choose between Super or SuperAlt as the prefix for hotkeys. - - - false - Show window previews - When multiple instances of the application are available, show their window previews - - - 'BOTH' - Hotkeys number keys - Which number keys are used for the hotkeys - - - 1']]]> - Keybinding to launch 1st dash app - - Keybinding to launch 1st app. - - - - 2']]]> - Keybinding to launch 2nd dash app - - Keybinding to launch 2nd app. - - - - 3']]]> - Keybinding to launch 3rd dash app - - Keybinding to launch 3rd app. - - - - 4']]]> - Keybinding to launch 4th dash app - - Keybinding to launch 4th app. - - - - 5']]]> - Keybinding to launch 5th dash app - - Keybinding to launch 5th app. - - - - 6']]]> - Keybinding to launch 6th dash app - - Keybinding to launch 6th app. - - - - 7']]]> - Keybinding to launch 7th dash app - - Keybinding to launch 7th app. - - - - 8']]]> - Keybinding to launch 8th dash app - - Keybinding to launch 8th app. - - - - 9']]]> - Keybinding to launch 9th dash app - - Keybinding to launch 9th app. - - - - 0']]]> - Keybinding to launch 10th dash app - - Keybinding to launch 10th app. - - - - 1']]]> - Keybinding to trigger 1st dash app with shift behavior - - Keybinding to trigger 1st app with shift behavior. - - - - 2']]]> - Keybinding to trigger 2nd dash app with shift behavior - - Keybinding to trigger 2nd app with shift behavior. - - - - 3']]]> - Keybinding to trigger 3rd dash app with shift behavior - - Keybinding to trigger 3rd app with shift behavior. - - - - 4']]]> - Keybinding to trigger 4th dash app with shift behavior - - Keybinding to trigger 4th app with shift behavior. - - - - 5']]]> - Keybinding to trigger 5th dash app with shift behavior - - Keybinding to trigger 5th app with shift behavior. - - - - 6']]]> - Keybinding to trigger 6th dash app with shift behavior - - Keybinding to trigger 6th app with shift behavior. - - - - 7']]]> - Keybinding to trigger 7th dash app with shift behavior - - Keybinding to trigger 7th app with shift behavior. - - - - 8']]]> - Keybinding to trigger 8th dash app with shift behavior - - Keybinding to trigger 8th app with shift behavior. - - - - 9']]]> - Keybinding to trigger 9th dash app with shift behavior - - Keybinding to trigger 9th app with shift behavior. - - - - 0']]]> - Keybinding to trigger 10th dash app with shift behavior - - Keybinding to trigger 10th app with shift behavior. - - - - 1']]]> - Keybinding to trigger 1st dash app - - Keybinding to either show or launch the 1st application in the dash. - - - - 2']]]> - Keybinding to trigger 2nd dash app - - Keybinding to either show or launch the 2nd application in the dash. - - - - 3']]]> - Keybinding to trigger 3rd dash app - - Keybinding to either show or launch the 3rd application in the dash. - - - - 4']]]> - Keybinding to trigger 4th dash app - - Keybinding to either show or launch the 4th application in the dash. - - - - 5']]]> - Keybinding to trigger 5th dash app - - Keybinding to either show or launch the 5th application in the dash. - - - - 6']]]> - Keybinding to trigger 6th dash app - - Keybinding to either show or launch the 6th application in the dash. - - - - 7']]]> - Keybinding to trigger 7th dash app - - Keybinding to either show or launch the 7th application in the dash. - - - - 8']]]> - Keybinding to trigger 8th dash app - - Keybinding to either show or launch the 8th application in the dash. - - - - 9']]]> - Keybinding to trigger 9th dash app - - Keybinding to either show or launch the 9th application in the dash. - - - - 0']]]> - Keybinding to trigger 10th dash app - - Keybinding to either show or launch the 10th application in the dash. - - - - KP_1']]]> - Keybinding to launch 1st dash app - - Keybinding to launch 1st app. - - - - KP_2']]]> - Keybinding to launch 2nd dash app - - Keybinding to launch 2nd app. - - - - KP_3']]]> - Keybinding to launch 3rd dash app - - Keybinding to launch 3rd app. - - - - KP_4']]]> - Keybinding to launch 4th dash app - - Keybinding to launch 4th app. - - - - KP_5']]]> - Keybinding to launch 5th dash app - - Keybinding to launch 5th app. - - - - KP_6']]]> - Keybinding to launch 6th dash app - - Keybinding to launch 6th app. - - - - KP_7']]]> - Keybinding to launch 7th dash app - - Keybinding to launch 7th app. - - - - KP_8']]]> - Keybinding to launch 8th dash app - - Keybinding to launch 8th app. - - - - KP_9']]]> - Keybinding to launch 9th dash app - - Keybinding to launch 9th app. - - - - KP_0']]]> - Keybinding to launch 10th dash app - - Keybinding to launch 10th app. - - - - KP_1']]]> - Keybinding to trigger 1st dash app with shift behavior - - Keybinding to trigger 1st app with shift behavior. - - - - KP_2']]]> - Keybinding to trigger 2nd dash app with shift behavior - - Keybinding to trigger 2nd app with shift behavior. - - - - KP_3']]]> - Keybinding to trigger 3rd dash app with shift behavior - - Keybinding to trigger 3rd app with shift behavior. - - - - KP_4']]]> - Keybinding to trigger 4th dash app with shift behavior - - Keybinding to trigger 4th app with shift behavior. - - - - KP_5']]]> - Keybinding to trigger 5th dash app with shift behavior - - Keybinding to trigger 5th app with shift behavior. - - - - KP_6']]]> - Keybinding to trigger 6th dash app with shift behavior - - Keybinding to trigger 6th app with shift behavior. - - - - KP_7']]]> - Keybinding to trigger 7th dash app with shift behavior - - Keybinding to trigger 7th app with shift behavior. - - - - KP_8']]]> - Keybinding to trigger 8th dash app with shift behavior - - Keybinding to trigger 8th app with shift behavior. - - - - KP_9']]]> - Keybinding to trigger 9th dash app with shift behavior - - Keybinding to trigger 9th app with shift behavior. - - - - KP_0']]]> - Keybinding to trigger 10th dash app with shift behavior - - Keybinding to trigger 10th app with shift behavior. - - - - KP_1']]]> - Keybinding to trigger 1st dash app - - Keybinding to either show or launch the 1st application in the dash. - - - - KP_2']]]> - Keybinding to trigger 2nd dash app - - Keybinding to either show or launch the 2nd application in the dash. - - - - KP_3']]]> - Keybinding to trigger 3rd dash app - - Keybinding to either show or launch the 3rd application in the dash. - - - - KP_4']]]> - Keybinding to trigger 4th dash app - - Keybinding to either show or launch the 4th application in the dash. - - - - KP_5']]]> - Keybinding to trigger 5th dash app - - Keybinding to either show or launch the 5th application in the dash. - - - - KP_6']]]> - Keybinding to trigger 6th dash app - - Keybinding to either show or launch the 6th application in the dash. - - - - KP_7']]]> - Keybinding to trigger 7th dash app - - Keybinding to either show or launch the 7th application in the dash. - - - - KP_8']]]> - Keybinding to trigger 8th dash app - - Keybinding to either show or launch the 8th application in the dash. - - - - KP_9']]]> - Keybinding to trigger 9th dash app - - Keybinding to either show or launch the 9th application in the dash. - - - - KP_0']]]> - Keybinding to trigger 10th dash app - - Keybinding to either show or launch the 10th application in the dash. - - - - true - Show progress bar on app icon - Whether to show progress bar overlay on app icon, for supported applications. - - - true - Show badge count on app icon - Whether to show badge count overlay on app icon, for supported applications. - - - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/stylesheet.css b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/stylesheet.css deleted file mode 100644 index d221bef..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/stylesheet.css +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -#dashtopanelTaskbar .dash-item-container > StWidget, -.dashtopanelMainPanel .show-apps { - margin: 0; - padding: 0; -} - -#dashtopanelScrollview .app-well-app .overview-icon, -.dashtopanelMainPanel .show-apps .overview-icon { - background: none; - border: none; - margin: 0; - padding: 0; -} - -#dashtopanelScrollview .app-well-app .overview-label { - /* must match TITLE_RIGHT_PADDING in apppicons.js */ - padding-right: 8px; -} - -#dashtopanelScrollview .app-well-app:hover .overview-icon, -#dashtopanelScrollview .app-well-app:focus .overview-icon { - background: none; -} - -.dashtopanelMainPanel .show-apps:hover .overview-icon, -#dashtopanelScrollview .app-well-app:hover .dtp-container, -#dashtopanelScrollview .app-well-app:focus .dtp-container { - background-color: rgba(238, 238, 236, 0.1); -} - -#dashtopanelScrollview .app-well-app:hover .dtp-container.animate-appicon-hover { - background: none; -} - -#dashtopanelScrollview .app-well-app:active .dtp-container { - background-color: rgba(238, 238, 236, 0.18); -} - -#dashtopanelScrollview .app-well-app .favorite { - background-color: rgba(80, 150, 255, 0.4); -} - -#dashtopanelScrollview .app-well-app-running-dot { - margin-bottom: 0; -} - -#dashtopanelTaskbar .scrollview-fade { - background-gradient-end: rgba(0, 0, 0, 0); -} - -.dashtopanelSecondaryMenu { - max-width: 400px; -} - -.dashtopanelMainPanel.vertical .panel-button { - text-align: center; -} - -.dashtopanelMainPanel.vertical .panel-button.vertical *, -.dashtopanelMainPanel.vertical .panel-button.clock-display * { - padding: 0; - margin: 0; -} - -.dashtopanelMainPanel.vertical .panel-button > *, -.dashtopanelMainPanel.vertical .panel-button.vertical > *, -.dashtopanelMainPanel.vertical .panel-button.vertical .system-status-icon, -.dashtopanelMainPanel.vertical .panel-button.clock-display > *, -.dashtopanelMainPanel.vertical .panel-button.clock-display .clock { - padding: 8px 0; -} - -.dashtopanelMainPanel.vertical .panel-button.clock-display { - -natural-hpadding: 0; - -minimum-hpadding: 0; -} - -#dashtopanelThumbnailList { - spacing: 0em; - padding: 0 1em; -} - -#dashtopanelThumbnailList .popup-menu-item { - padding: 0; - border-radius: 5px; - spacing: 0; -} - -#dashtopanelThumbnailList .window-box { - padding: 0; - spacing: 0; -} - -#dashtopanelThumbnailList .preview-window-title { - padding-top: 1em; -} - -.popup-menu.panel-menu { - margin-bottom: 0; -} - -#panel #panelLeft, #panel #panelCenter { - spacing: 0px; -} - -.showdesktop-button-dark-hovered { - background-color: rgba(200, 200, 200, .4); -} - -.showdesktop-button-light-hovered { - background-color: rgba(55, 55, 55, .4); -} - -#dashtopanelScrollview .badge { - color: rgba(255, 255, 255, 1); - font-weight: bold; - text-align: center; -} - -#dashtopanelScrollview .number-overlay { - background-color: rgba(0,0,0,0.8); -} - -#dashtopanelScrollview .notification-badge { - background-color: rgba(255,0,0,0.8); -} - -#dashtopanelScrollview .progress-bar { - /* Customization of the progress bar style, e.g.: - -progress-bar-background: rgba(0.8, 0.8, 0.8, 1); - -progress-bar-border: rgba(0.9, 0.9, 0.9, 1); - */ -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/taskbar.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/taskbar.js deleted file mode 100644 index f3018f3..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/taskbar.js +++ /dev/null @@ -1,1570 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * Some code was also adapted from the upstream Gnome Shell source code. - */ - - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Graphene from 'gi://Graphene'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js'; -import * as Dash from 'resource:///org/gnome/shell/ui/dash.js'; -import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as AppIcons from './appIcons.js'; -import * as PanelManager from './panelManager.js'; -import * as PanelSettings from './panelSettings.js'; -import * as Pos from './panelPositions.js'; -import * as Utils from './utils.js'; -import * as WindowPreview from './windowPreview.js'; -import {SETTINGS} from './extension.js'; - -const SearchController = Main.overview.searchController; - -export const DASH_ANIMATION_TIME = Dash.DASH_ANIMATION_TIME / (Dash.DASH_ANIMATION_TIME > 1 ? 1000 : 1); -const DASH_ITEM_HOVER_TIMEOUT = Dash.DASH_ITEM_HOVER_TIMEOUT; -export const MIN_ICON_SIZE = 4; - -const T1 = 'ensureAppIconVisibilityTimeout' -const T2 = 'showLabelTimeout' -const T3 = 'resetHoverTimeout' - - -/** - * Extend DashItemContainer - * - * - set label position based on taskbar orientation - * - * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. - * thus use this ugly pattern. - */ - -export function extendDashItemContainer(dashItemContainer) { - dashItemContainer.showLabel = AppIcons.ItemShowLabel; -} - -const iconAnimationSettings = { - _getDictValue(key) { - let type = SETTINGS.get_string('animate-appicon-hover-animation-type'); - return SETTINGS.get_value(key).deep_unpack()[type] || 0; - }, - - get type() { - if (!SETTINGS.get_boolean('animate-appicon-hover')) - return ""; - - return SETTINGS.get_string('animate-appicon-hover-animation-type'); - }, - - get convexity() { - return Math.max(0, this._getDictValue('animate-appicon-hover-animation-convexity')); - }, - - get duration() { - return this._getDictValue('animate-appicon-hover-animation-duration'); - }, - - get extent() { - return Math.max(1, this._getDictValue('animate-appicon-hover-animation-extent')); - }, - - get rotation() { - return this._getDictValue('animate-appicon-hover-animation-rotation'); - }, - - get travel() { - return Math.max(0, this._getDictValue('animate-appicon-hover-animation-travel')); - }, - - get zoom() { - return Math.max(1, this._getDictValue('animate-appicon-hover-animation-zoom')); - }, -}; - -/* This class is a fork of the upstream DashActor class (ui.dash.js) - * - * Summary of changes: - * - modified chldBox calculations for when 'show-apps-at-top' option is checked - * - handle horizontal dash - */ -export const TaskbarActor = GObject.registerClass({ -}, class TaskbarActor extends St.Widget { - _init(delegate) { - this._delegate = delegate; - this._currentBackgroundColor = 0; - super._init({ name: 'dashtopanelTaskbar', - layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation[delegate.dtpPanel.getOrientation().toUpperCase()] }), - clip_to_allocation: true }); - } - - vfunc_allocate(box) { - this.set_allocation(box); - - let panel = this._delegate.dtpPanel; - let availFixedSize = box[panel.fixedCoord.c2] - box[panel.fixedCoord.c1]; - let availVarSize = box[panel.varCoord.c2] - box[panel.varCoord.c1]; - let [dummy, scrollview, leftFade, rightFade] = this.get_children(); - let [, natSize] = this[panel.sizeFunc](availFixedSize); - let childBox = new Clutter.ActorBox(); - let orientation = panel.getOrientation(); - - dummy.allocate(childBox); - - childBox[panel.varCoord.c1] = box[panel.varCoord.c1]; - childBox[panel.varCoord.c2] = Math.min(availVarSize, natSize); - childBox[panel.fixedCoord.c1] = box[panel.fixedCoord.c1]; - childBox[panel.fixedCoord.c2] = box[panel.fixedCoord.c2]; - - scrollview.allocate(childBox); - - let [value, , upper, , , pageSize] = scrollview[orientation[0] + 'scroll'].adjustment.get_values(); - upper = Math.floor(upper); - scrollview._dtpFadeSize = upper > pageSize ? this._delegate.iconSize : 0; - - if (this._currentBackgroundColor !== panel.dynamicTransparency.currentBackgroundColor) { - this._currentBackgroundColor = panel.dynamicTransparency.currentBackgroundColor; - let gradientStyle = 'background-gradient-start: ' + this._currentBackgroundColor + - 'background-gradient-direction: ' + orientation; - - leftFade.set_style(gradientStyle); - rightFade.set_style(gradientStyle); - } - - childBox[panel.varCoord.c2] = childBox[panel.varCoord.c1] + (value > 0 ? scrollview._dtpFadeSize : 0); - leftFade.allocate(childBox); - - childBox[panel.varCoord.c1] = box[panel.varCoord.c2] - (value + pageSize < upper ? scrollview._dtpFadeSize : 0); - childBox[panel.varCoord.c2] = box[panel.varCoord.c2]; - rightFade.allocate(childBox); - } - - // We want to request the natural size of all our children - // as our natural width, so we chain up to StWidget (which - // then calls BoxLayout) - vfunc_get_preferred_width(forHeight) { - let [, natWidth] = St.Widget.prototype.vfunc_get_preferred_width.call(this, forHeight); - - return [0, natWidth]; - } - - vfunc_get_preferred_height(forWidth) { - let [, natHeight] = St.Widget.prototype.vfunc_get_preferred_height.call(this, forWidth); - - return [0, natHeight]; - } -}); - -/* This class is a fork of the upstream dash class (ui.dash.js) - * - * Summary of changes: - * - disconnect global signals adding a destroy method; - * - play animations even when not in overview mode - * - set a maximum icon size - * - show running and/or favorite applications - * - emit a custom signal when an app icon is added - * - Add scrollview - * Ensure actor is visible on keyfocus inside the scrollview - * - add 128px icon size, might be useful for hidpi display - * - Sync minimization application target position. - */ - -export const Taskbar = class extends EventEmitter { - - constructor(panel) { - super(); - - this.dtpPanel = panel; - - // start at smallest size due to running indicator drawing area expanding but not shrinking - this.iconSize = 16; - - this._shownInitially = false; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._timeoutsHandler = new Utils.TimeoutsHandler(); - - this._labelShowing = false; - this.fullScrollView = 0; - - let isVertical = panel.checkIfVertical(); - - this._box = new St.BoxLayout({ vertical: isVertical, - clip_to_allocation: false, - x_align: Clutter.ActorAlign.START, - y_align: Clutter.ActorAlign.START }); - - this._container = new TaskbarActor(this); - this._scrollView = new St.ScrollView({ name: 'dashtopanelScrollview', - hscrollbar_policy: St.PolicyType.NEVER, - vscrollbar_policy: St.PolicyType.NEVER, - enable_mouse_scrolling: true }); - - this._scrollView.connect('leave-event', this._onLeaveEvent.bind(this)); - this._scrollView.connect('motion-event', this._onMotionEvent.bind(this)); - this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this)); - this._scrollView.add_actor(this._box); - - this._showAppsIconWrapper = panel.showAppsIconWrapper; - this._showAppsIconWrapper.connect('menu-state-changed', (showAppsIconWrapper, opened) => { - this._itemMenuStateChanged(showAppsIconWrapper, opened); - }); - // an instance of the showAppsIcon class is encapsulated in the wrapper - this._showAppsIcon = this._showAppsIconWrapper.realShowAppsIcon; - this.showAppsButton = this._showAppsIcon.toggleButton; - - if (isVertical) { - this.showAppsButton.set_width(panel.geom.w); - } - - this.showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this)); - - this.showAppsButton.checked = (SearchController._showAppsButton) ? SearchController._showAppsButton.checked : false; - - this._showAppsIcon.childScale = 1; - this._showAppsIcon.childOpacity = 255; - this._showAppsIcon.icon.setIconSize(this.iconSize); - this._hookUpLabel(this._showAppsIcon, this._showAppsIconWrapper); - - this._container.add_child(new St.Widget({ width: 0, reactive: false })); - this._container.add_actor(this._scrollView); - - let orientation = panel.getOrientation(); - let fadeStyle = 'background-gradient-direction:' + orientation; - let fade1 = new St.Widget({ style_class: 'scrollview-fade', reactive: false }); - let fade2 = new St.Widget({ style_class: 'scrollview-fade', - reactive: false, - pivot_point: new Graphene.Point({ x: .5, y: .5 }), - rotation_angle_z: 180 }); - - fade1.set_style(fadeStyle); - fade2.set_style(fadeStyle); - - this._container.add_actor(fade1); - this._container.add_actor(fade2); - - this.previewMenu = new WindowPreview.PreviewMenu(panel); - this.previewMenu.enable(); - - let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; - this.actor = new St.Bin({ - child: this._container, - y_align: Clutter.ActorAlign.START, - x_align: rtl ? Clutter.ActorAlign.END : Clutter.ActorAlign.START - }); - - let adjustment = this._scrollView[orientation[0] + 'scroll'].adjustment; - - this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); - - this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); - - this._appSystem = Shell.AppSystem.get_default(); - - this.iconAnimator = new PanelManager.IconAnimator(this.dtpPanel.panel); - - this._signalsHandler.add( - [ - this.dtpPanel.panel, - 'notify::height', - () => this._queueRedisplay() - ], - [ - this.dtpPanel.panel, - 'notify::width', - () => this._queueRedisplay() - ], - [ - this._appSystem, - 'installed-changed', - () => { - AppFavorites.getAppFavorites().reload(); - this._queueRedisplay(); - } - ], - [ - this._appSystem, - 'app-state-changed', - this._queueRedisplay.bind(this) - ], - [ - AppFavorites.getAppFavorites(), - 'changed', - this._queueRedisplay.bind(this) - ], - [ - global.window_manager, - 'switch-workspace', - () => this._connectWorkspaceSignals() - ], - [ - Utils.DisplayWrapper.getScreen(), - [ - 'window-entered-monitor', - 'window-left-monitor' - ], - () => { - if (SETTINGS.get_boolean('isolate-monitors')) { - this._queueRedisplay(); - } - } - ], - [ - Main.overview, - 'item-drag-begin', - this._onDragBegin.bind(this) - ], - [ - Main.overview, - 'item-drag-end', - this._onDragEnd.bind(this) - ], - [ - Main.overview, - 'item-drag-cancelled', - this._onDragCancelled.bind(this) - ], - [ - // Ensure the ShowAppsButton status is kept in sync - SearchController._showAppsButton, - 'notify::checked', - this._syncShowAppsButtonToggled.bind(this) - ], - [ - SETTINGS, - [ - 'changed::dot-size', - 'changed::show-favorites', - 'changed::show-running-apps', - 'changed::show-favorites-all-monitors' - ], - () => { - setAttributes() - this._redisplay() - } - ], - [ - SETTINGS, - 'changed::group-apps', - () => { - setAttributes() - this._connectWorkspaceSignals(); - } - ], - [ - SETTINGS, - [ - 'changed::group-apps-use-launchers', - 'changed::taskbar-locked' - ], - () => { - setAttributes() - this.resetAppIcons() - } - ], - [ - adjustment, - [ - 'notify::upper', - 'notify::pageSize' - ], - () => this._onScrollSizeChange(adjustment) - ] - ); - - let setAttributes = () => { - this.isGroupApps = SETTINGS.get_boolean('group-apps'); - this.usingLaunchers = !this.isGroupApps && SETTINGS.get_boolean('group-apps-use-launchers'); - this.showFavorites = SETTINGS.get_boolean('show-favorites') && - (this.dtpPanel.isPrimary || SETTINGS.get_boolean('show-favorites-all-monitors')) - this.showRunningApps = SETTINGS.get_boolean('show-running-apps') - this.allowSplitApps = this.usingLaunchers || (!this.isGroupApps && !this.showFavorites) - } - - setAttributes() - - this._onScrollSizeChange(adjustment); - this._connectWorkspaceSignals(); - } - - destroy() { - if (this._waitIdleId) { - GLib.source_remove(this._waitIdleId); - this._waitIdleId = 0; - } - - this._timeoutsHandler.destroy(); - this.iconAnimator.destroy(); - - this._signalsHandler.destroy(); - this._signalsHandler = 0; - - this._container.destroy(); - - this.previewMenu.disable(); - this.previewMenu.destroy(); - - this._disconnectWorkspaceSignals(); - } - - _dropIconAnimations() { - this._getTaskbarIcons().forEach(item => { - item.raise(0); - item.stretch(0); - }); - } - - _updateIconAnimations(pointerX, pointerY) { - this._iconAnimationTimestamp = Date.now(); - let type = iconAnimationSettings.type; - - if (!pointerX || !pointerY) - [pointerX, pointerY] = global.get_pointer(); - - this._getTaskbarIcons().forEach(item => { - let [x, y] = item.get_transformed_position(); - let [width, height] = item.get_transformed_size(); - let [centerX, centerY] = [x + width / 2, y + height / 2]; - let size = this._box.vertical ? height : width; - let difference = this._box.vertical ? pointerY - centerY : pointerX - centerX; - let distance = Math.abs(difference); - let maxDistance = (iconAnimationSettings.extent / 2) * size; - - if (type == 'PLANK') { - // Make the position stable for items that are far from the pointer. - let translation = distance <= maxDistance ? - distance / (2 + 8 * distance / maxDistance) : - // the previous expression with distance = maxDistance - maxDistance / 10; - - if (difference > 0) - translation *= -1; - - item.stretch(translation); - } - - if (distance <= maxDistance) { - let level = (maxDistance - distance) / maxDistance; - level = Math.pow(level, iconAnimationSettings.convexity); - item.raise(level); - } else { - item.raise(0); - } - }); - } - - _onLeaveEvent(actor) { - let [stageX, stageY] = global.get_pointer(); - let [success, x, y] = actor.transform_stage_point(stageX, stageY); - if (success && !actor.allocation.contains(x, y) && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK')) - this._dropIconAnimations(); - - return Clutter.EVENT_PROPAGATE; - } - - _onMotionEvent(actor_, event) { - if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') { - let timestamp = Date.now(); - if (!this._iconAnimationTimestamp || - (timestamp - this._iconAnimationTimestamp >= iconAnimationSettings.duration / 2)) { - let [pointerX, pointerY] = event.get_coords(); - this._updateIconAnimations(pointerX, pointerY); - } - } - - return Clutter.EVENT_PROPAGATE; - } - - _onScrollEvent(actor, event) { - - let orientation = this.dtpPanel.getOrientation(); - - // reset timeout to avid conflicts with the mousehover event - this._timeoutsHandler.add([T1, 0, - () => this._swiping = false - ]); - - // Skip to avoid double events mouse - if (event.is_pointer_emulated()) - return Clutter.EVENT_STOP; - - let adjustment, delta; - - adjustment = this._scrollView[orientation[0] + 'scroll'].get_adjustment(); - - let increment = adjustment.step_increment; - - switch ( event.get_scroll_direction() ) { - case Clutter.ScrollDirection.UP: - case Clutter.ScrollDirection.LEFT: - delta = -increment; - break; - case Clutter.ScrollDirection.DOWN: - case Clutter.ScrollDirection.RIGHT: - delta = +increment; - break; - case Clutter.ScrollDirection.SMOOTH: - let [dx, dy] = event.get_scroll_delta(); - delta = dy*increment; - delta += dx*increment; - break; - - } - - adjustment.set_value(adjustment.get_value() + delta); - - return Clutter.EVENT_STOP; - - } - - _onScrollSizeChange(adjustment) { - // Update minimization animation target position on scrollview change. - this._updateAppIcons(); - - // When applications are ungrouped and there is some empty space on the horizontal taskbar, - // force a fixed label width to prevent the icons from "wiggling" when an animation runs - // (adding or removing an icon). When the taskbar is full, revert to a dynamic label width - // to allow them to resize and make room for new icons. - if (!this.dtpPanel.checkIfVertical() && !this.isGroupApps) { - let initial = this.fullScrollView; - - if (!this.fullScrollView && Math.floor(adjustment.upper) > adjustment.page_size) { - this.fullScrollView = adjustment.page_size; - } else if (adjustment.page_size < this.fullScrollView) { - this.fullScrollView = 0; - } - - if (initial != this.fullScrollView && !this._waitIdleId) { - this._waitIdleId = GLib.idle_add(() => { - this._getAppIcons().forEach(a => a.updateTitleStyle()) - this._waitIdleId = 0; - - return GLib.SOURCE_REMOVE; - }); - } - } - } - - _onDragBegin() { - this._dragCancelled = false; - this._dragMonitor = { - dragMotion: this._onDragMotion.bind(this) - }; - DND.addDragMonitor(this._dragMonitor); - - if (this._box.get_n_children() == 0) { - this._emptyDropTarget = new Dash.EmptyDropTargetItem(); - this._box.insert_child_at_index(this._emptyDropTarget, 0); - this._emptyDropTarget.show(true); - } - - this._toggleFavoriteHighlight(true); - } - - _onDragCancelled() { - this._dragCancelled = true; - - if (this._dragInfo) { - this._box.set_child_at_index(this._dragInfo[1]._dashItemContainer, this._dragInfo[0]); - } - - this._endDrag(); - } - - _onDragEnd() { - if (this._dragCancelled) - return; - - this._endDrag(); - } - - _endDrag() { - if (this._dragInfo && this._dragInfo[1]._dashItemContainer instanceof DragPlaceholderItem) { - this._box.remove_child(this._dragInfo[1]._dashItemContainer); - this._dragInfo[1]._dashItemContainer.destroy(); - delete this._dragInfo[1]._dashItemContainer; - } - - this._dragInfo = null; - this._clearEmptyDropTarget(); - this._showAppsIcon.setDragApp(null); - DND.removeDragMonitor(this._dragMonitor); - - this._dragMonitor = null; - this.emit('end-drag'); - - this._toggleFavoriteHighlight(); - } - - _onDragMotion(dragEvent) { - let app = Dash.Dash.getAppFromSource(dragEvent.source); - if (app == null) - return DND.DragMotionResult.CONTINUE; - - let showAppsHovered = this._showAppsIcon.contains(dragEvent.targetActor); - - if (showAppsHovered) - this._showAppsIcon.setDragApp(app); - else - this._showAppsIcon.setDragApp(null); - - return DND.DragMotionResult.CONTINUE; - } - - _toggleFavoriteHighlight(show) { - let appFavorites = AppFavorites.getAppFavorites(); - let cssFuncName = (show ? 'add' : 'remove') + '_style_class_name'; - - if (this.showFavorites) - this._getAppIcons().filter(appIcon => (this.usingLaunchers && appIcon.isLauncher) || - (!this.usingLaunchers && appFavorites.isFavorite(appIcon.app.get_id()))) - .forEach(fav => fav._container[cssFuncName]('favorite')); - } - - handleIsolatedWorkspaceSwitch() { - this._shownInitially = this.isGroupApps; - this._queueRedisplay(); - } - - _connectWorkspaceSignals() { - this._disconnectWorkspaceSignals(); - - this._lastWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - - this._workspaceWindowAddedId = this._lastWorkspace.connect('window-added', () => this._queueRedisplay()); - this._workspaceWindowRemovedId = this._lastWorkspace.connect('window-removed', () => this._queueRedisplay()); - } - - _disconnectWorkspaceSignals() { - if (this._lastWorkspace) { - this._lastWorkspace.disconnect(this._workspaceWindowAddedId); - this._lastWorkspace.disconnect(this._workspaceWindowRemovedId); - - this._lastWorkspace = null; - } - } - - _queueRedisplay() { - Main.queueDeferredWork(this._workId); - } - - _hookUpLabel(item, syncHandler) { - item.child.connect('notify::hover', () => { - this._syncLabel(item, syncHandler); - }); - - syncHandler.connect('sync-tooltip', () => { - this._syncLabel(item, syncHandler); - }); - } - - _createAppItem(app, window, isLauncher) { - let appIcon = new AppIcons.TaskbarAppIcon( - { - app, - window, - isLauncher - }, - this.dtpPanel, - { - setSizeManually: true, - showLabel: false, - isDraggable: !SETTINGS.get_boolean('taskbar-locked'), - }, - this.previewMenu, - this.iconAnimator - ); - - if (appIcon._draggable) { - appIcon._draggable.connect('drag-begin', - () => { - appIcon.opacity = 0; - appIcon.isDragged = 1; - this._dropIconAnimations(); - }); - appIcon._draggable.connect('drag-end', - () => { - appIcon.opacity = 255; - delete appIcon.isDragged; - this._updateAppIcons(); - }); - } - - appIcon.connect('menu-state-changed', - (appIcon, opened) => { - this._itemMenuStateChanged(item, opened); - }); - - let item = new TaskbarItemContainer(); - - item._dtpPanel = this.dtpPanel - extendDashItemContainer(item); - - item.setChild(appIcon); - appIcon._dashItemContainer = item; - - appIcon.connect('notify::hover', () => { - if (appIcon.hover){ - this._timeoutsHandler.add([T1, 100, - () => Utils.ensureActorVisibleInScrollView(this._scrollView, appIcon, this._scrollView._dtpFadeSize) - ]) - - if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE') - appIcon.get_parent().raise(1); - else if (!appIcon.isDragged && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK')) - this._updateIconAnimations(); - } else { - this._timeoutsHandler.remove(T1) - - if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE') - appIcon.get_parent().raise(0); - } - }); - - appIcon.connect('clicked', - (actor) => { - Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize); - }); - - appIcon.connect('key-focus-in', (actor) => { - let [x_shift, y_shift] = Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize); - - // This signal is triggered also by mouse click. The popup menu is opened at the original - // coordinates. Thus correct for the shift which is going to be applied to the scrollview. - if (appIcon._menu) { - appIcon._menu._boxPointer.xOffset = -x_shift; - appIcon._menu._boxPointer.yOffset = -y_shift; - } - }); - - // Override default AppIcon label_actor, now the - // accessible_name is set at DashItemContainer.setLabelText - appIcon.label_actor = null; - item.setLabelText(app.get_name()); - - appIcon.icon.setIconSize(this.iconSize); - this._hookUpLabel(item, appIcon); - - return item; - } - - // Return an array with the "proper" appIcons currently in the taskbar - _getAppIcons() { - // Only consider children which are "proper" icons and which are not - // animating out (which means they will be destroyed at the end of - // the animation) - return this._getTaskbarIcons().map(function(actor){ - return actor.child._delegate; - }); - } - - _getTaskbarIcons(includeAnimated) { - return this._box.get_children().filter(function(actor) { - return actor.child && - actor.child._delegate && - actor.child._delegate.icon && - (includeAnimated || !actor.animatingOut); - }); - } - - _updateAppIcons() { - let appIcons = this._getAppIcons(); - - appIcons.filter(icon => icon.constructor === AppIcons.TaskbarAppIcon).forEach(icon => { - icon.updateIcon(); - }); - } - - _itemMenuStateChanged(item, opened) { - // When the menu closes, it calls sync_hover, which means - // that the notify::hover handler does everything we need to. - if (opened) { - this._timeoutsHandler.remove(T2) - - item.hideLabel(); - } else { - // I want to listen from outside when a menu is closed. I used to - // add a custom signal to the appIcon, since gnome 3.8 the signal - // calling this callback was added upstream. - this.emit('menu-closed'); - - // The icon menu grabs the events and, once it is closed, the pointer is maybe - // no longer over the taskbar and the animations are not dropped. - if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') { - this._scrollView.sync_hover(); - if (!this._scrollView.hover) - this._dropIconAnimations(); - } - } - } - - _syncLabel(item, syncHandler) { - let shouldShow = syncHandler ? syncHandler.shouldShowTooltip() : item.child.get_hover(); - - if (shouldShow) { - if (!this._timeoutsHandler.getId(T2)) { - let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT; - - this._timeoutsHandler.add([T2, timeout, - () => { - this._labelShowing = true; - item.showLabel(); - } - ]); - - this._timeoutsHandler.remove(T3) - } - } else { - this._timeoutsHandler.remove(T2) - - item.hideLabel(); - if (this._labelShowing) { - this._timeoutsHandler.add([T3, DASH_ITEM_HOVER_TIMEOUT, - () => this._labelShowing = false - ]); - } - } - } - - _adjustIconSize() { - const thisMonitorIndex = this.dtpPanel.monitor.index; - let panelSize = PanelSettings.getPanelSize(SETTINGS, thisMonitorIndex); - let availSize = panelSize - SETTINGS.get_int('appicon-padding') * 2; - let minIconSize = MIN_ICON_SIZE + panelSize % 2; - - if (availSize == this.iconSize) - return; - - if (availSize < minIconSize) { - availSize = minIconSize; - } - - // For the icon size, we only consider children which are "proper" - // icons and which are not animating out (which means they will be - // destroyed at the end of the animation) - let iconChildren = this._getTaskbarIcons().concat([this._showAppsIcon]); - let scale = this.iconSize / availSize; - - this.iconSize = availSize; - - for (let i = 0; i < iconChildren.length; i++) { - let icon = iconChildren[i].child._delegate.icon; - - // Set the new size immediately, to keep the icons' sizes - // in sync with this.iconSize - icon.setIconSize(this.iconSize); - - // Don't animate the icon size change when the overview - // is transitioning, or when initially filling - // the taskbar - if (Main.overview.animationInProgress || - !this._shownInitially) - continue; - - let [targetWidth, targetHeight] = icon.icon.get_size(); - - // Scale the icon's texture to the previous size and - // tween to the new size - icon.icon.set_size(icon.icon.width * scale, icon.icon.height * scale); - - Utils.animate(icon.icon, - { width: targetWidth, - height: targetHeight, - time: DASH_ANIMATION_TIME, - transition: 'easeOutQuad', - }); - } - } - - sortAppsCompareFunction(appA, appB) { - return getAppStableSequence(appA, this.dtpPanel.monitor) - - getAppStableSequence(appB, this.dtpPanel.monitor); - } - - getAppInfos() { - //get the user's favorite apps - let favoriteApps = this.showFavorites ? AppFavorites.getAppFavorites().getFavorites() : []; - - //find the apps that should be in the taskbar: the favorites first, then add the running apps - // When using isolation, we filter out apps that have no windows in - // the current workspace (this check is done in AppIcons.getInterestingWindows) - let runningApps = this.showRunningApps ? this._getRunningApps().sort(this.sortAppsCompareFunction.bind(this)) : []; - - if (this.allowSplitApps) { - return this._createAppInfos(favoriteApps, [], true) - .concat(this._createAppInfos(runningApps) - .filter(appInfo => appInfo.windows.length)); - } else { - return this._createAppInfos(favoriteApps.concat(runningApps.filter(app => favoriteApps.indexOf(app) < 0))) - .filter(appInfo => appInfo.windows.length || favoriteApps.indexOf(appInfo.app) >= 0); - } - } - - _redisplay() { - if (!this._signalsHandler) { - return; - } - - //get the currently displayed appIcons - let currentAppIcons = this._getTaskbarIcons(); - let expectedAppInfos = this.getAppInfos(); - - //remove the appIcons which are not in the expected apps list - for (let i = currentAppIcons.length - 1; i > -1; --i) { - let appIcon = currentAppIcons[i].child._delegate; - let appIndex = Utils.findIndex(expectedAppInfos, appInfo => appInfo.app == appIcon.app && - (!this.allowSplitApps || this.isGroupApps || appInfo.windows[0] == appIcon.window) && - appInfo.isLauncher == appIcon.isLauncher); - - if (appIndex < 0 || - (appIcon.window && (this.isGroupApps || expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) || - (!appIcon.window && !appIcon.isLauncher && - !this.isGroupApps && expectedAppInfos[appIndex].windows.length)) { - currentAppIcons[i][this._shownInitially ? 'animateOutAndDestroy' : 'destroy'](); - currentAppIcons.splice(i, 1); - } - } - - //if needed, reorder the existing appIcons and create the missing ones - let currentPosition = 0; - for (let i = 0, l = expectedAppInfos.length; i < l; ++i) { - let neededAppIcons = this.isGroupApps || !expectedAppInfos[i].windows.length ? - [{ app: expectedAppInfos[i].app, window: null, isLauncher: expectedAppInfos[i].isLauncher }] : - expectedAppInfos[i].windows.map(window => ({ app: expectedAppInfos[i].app, window: window, isLauncher: false })); - - for (let j = 0, ll = neededAppIcons.length; j < ll; ++j) { - //check if the icon already exists - let matchingAppIconIndex = Utils.findIndex(currentAppIcons, appIcon => appIcon.child._delegate.app == neededAppIcons[j].app && - appIcon.child._delegate.window == neededAppIcons[j].window); - - if (matchingAppIconIndex > 0 && matchingAppIconIndex != currentPosition) { - //moved icon, reposition it - this._box.remove_child(currentAppIcons[matchingAppIconIndex]); - this._box.insert_child_at_index(currentAppIcons[matchingAppIconIndex], currentPosition); - } else if (matchingAppIconIndex < 0) { - //the icon doesn't exist yet, create a new one - let newAppIcon = this._createAppItem(neededAppIcons[j].app, neededAppIcons[j].window, neededAppIcons[j].isLauncher); - - this._box.insert_child_at_index(newAppIcon, currentPosition); - currentAppIcons.splice(currentPosition, 0, newAppIcon); - - // Skip animations on first run when adding the initial set - // of items, to avoid all items zooming in at once - newAppIcon.show(this._shownInitially); - } - - ++currentPosition; - } - } - - this._adjustIconSize(); - - // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 - // Without it, StBoxLayout may use a stale size cache - this._box.queue_relayout(); - - // This is required for icon reordering when the scrollview is used. - this._updateAppIcons(); - - // This will update the size, and the corresponding number for each icon on the primary panel - if (this.dtpPanel.isPrimary) { - this._updateNumberOverlay(); - } - - this._shownInitially = true; - } - - _getRunningApps() { - let tracker = Shell.WindowTracker.get_default(); - let windows = global.get_window_actors(); - let apps = []; - - for (let i = 0, l = windows.length; i < l; ++i) { - let app = tracker.get_window_app(windows[i].metaWindow); - - if (app && apps.indexOf(app) < 0) { - apps.push(app); - } - } - - return apps; - } - - _createAppInfos(apps, defaultWindows, defaultIsLauncher) { - if (this.allowSplitApps && !defaultIsLauncher) { - let separateApps = [] - - if (apps.length) { - let tracker = Shell.WindowTracker.get_default(); - let windows = AppIcons.getInterestingWindows(null, this.dtpPanel.monitor) - .sort(sortWindowsCompareFunction) - - windows.forEach(w => { - let windowApp = tracker.get_window_app(w) - - if (apps.indexOf(windowApp) >= 0) - separateApps.push({ - app: windowApp, - isLauncher: false, - windows: [w] - }) - }) - } - - return separateApps - } - - return apps.map(app => ({ - app: app, - isLauncher: defaultIsLauncher || false, - windows: defaultWindows || AppIcons.getInterestingWindows(app, this.dtpPanel.monitor) - .sort(sortWindowsCompareFunction) - })); - } - - // Reset the displayed apps icon to mantain the correct order - resetAppIcons (geometryChange) { - let children = this._getTaskbarIcons(true); - - for (let i = 0; i < children.length; i++) { - let item = children[i]; - item.destroy(); - } - - // to avoid ugly animations, just suppress them like when taskbar is first loaded. - this._shownInitially = false; - this._redisplay(); - - if (geometryChange && this.dtpPanel.checkIfVertical()) { - this.previewMenu._updateClip(); - } - } - - _updateNumberOverlay() { - let seenApps = {}; - let counter = 0; - - this._getAppIcons().forEach(icon => { - if (!seenApps[icon.app] || this.allowSplitApps) { - seenApps[icon.app] = 1; - counter++; - } - - if (counter <= 10) { - icon.setNumberOverlay(counter == 10 ? 0 : counter); - } else { - // No overlay after 10 - icon.setNumberOverlay(-1); - } - - icon.updateHotkeyNumberOverlay(); - }); - - if (SETTINGS.get_boolean('hot-keys') && - SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS') - this.toggleNumberOverlay(true); - } - - toggleNumberOverlay(activate) { - let appIcons = this._getAppIcons(); - appIcons.forEach(function(icon) { - icon.toggleNumberOverlay(activate); - }); - } - - _clearEmptyDropTarget() { - if (this._emptyDropTarget) { - this._emptyDropTarget.animateOutAndDestroy(); - this._emptyDropTarget = null; - } - } - - handleDragOver(source, actor, x, y, time) { - if (source == Main.xdndHandler) - return DND.DragMotionResult.CONTINUE; - - // Don't allow favoriting of transient apps - if (source.app == null || source.app.is_window_backed()) - return DND.DragMotionResult.NO_DROP; - - if (!this._settings.is_writable('favorite-apps')) - return DND.DragMotionResult.NO_DROP; - - let isVertical = this.dtpPanel.checkIfVertical(); - - if (!this._box.contains(source) && !source._dashItemContainer) { - //not an appIcon of the taskbar, probably from the applications view - source._dashItemContainer = new DragPlaceholderItem(source, this.iconSize, isVertical); - this._box.insert_child_above(source._dashItemContainer, null); - } - - let sizeProp = isVertical ? 'height' : 'width'; - let posProp = isVertical ? 'y' : 'x'; - let pos = isVertical ? y : x; - - let currentAppIcons = this._getAppIcons(); - let sourceIndex = currentAppIcons.indexOf(source); - let hoveredIndex = Utils.findIndex(currentAppIcons, - appIcon => pos >= appIcon._dashItemContainer[posProp] && - pos <= (appIcon._dashItemContainer[posProp] + appIcon._dashItemContainer[sizeProp])); - - if (!this._dragInfo) { - this._dragInfo = [sourceIndex, source]; - } - - if (hoveredIndex >= 0) { - let isLeft = pos < currentAppIcons[hoveredIndex]._dashItemContainer[posProp] + currentAppIcons[hoveredIndex]._dashItemContainer[sizeProp] * .5; - let prevIcon = currentAppIcons[hoveredIndex - 1] - let nextIcon = currentAppIcons[hoveredIndex + 1] - - // Don't allow positioning before or after self and between icons of same app if ungrouped and showing favorites - if (!(hoveredIndex === sourceIndex || - (isLeft && hoveredIndex - 1 == sourceIndex) || - (!this.allowSplitApps && isLeft && hoveredIndex - 1 >= 0 && source.app != prevIcon.app && - prevIcon.app == currentAppIcons[hoveredIndex].app) || - (!isLeft && hoveredIndex + 1 == sourceIndex) || - (!this.allowSplitApps && !isLeft && hoveredIndex + 1 < currentAppIcons.length && source.app != nextIcon.app && - nextIcon.app == currentAppIcons[hoveredIndex].app))) { - this._box.set_child_at_index(source._dashItemContainer, hoveredIndex); - - // Ensure the next and previous icon are visible when moving the icon - // (I assume there's room for both of them) - if (hoveredIndex > 1) - Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex-1], this._scrollView._dtpFadeSize); - if (hoveredIndex < this._box.get_children().length-1) - Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex+1], this._scrollView._dtpFadeSize); - } - } - - return this._dragInfo[0] !== sourceIndex ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.CONTINUE; - } - - // Draggable target interface - acceptDrop (source, actor, x, y, time) { - // Don't allow favoriting of transient apps - if (!this._dragInfo || !source.app || source.app.is_window_backed() || - !this._settings.is_writable('favorite-apps')) { - return false; - } - - let appIcons = this._getAppIcons(); - let sourceIndex = appIcons.indexOf(source); - let usingLaunchers = !this.isGroupApps && this.usingLaunchers; - - // dragging the icon to its original position - if (this._dragInfo[0] === sourceIndex) { - return true; - } - - let appFavorites = AppFavorites.getAppFavorites(); - let sourceAppId = source.app.get_id(); - let appIsFavorite = this.showFavorites && appFavorites.isFavorite(sourceAppId); - let replacingIndex = sourceIndex + (sourceIndex > this._dragInfo[0] ? -1 : 1); - let favoriteIndex = replacingIndex >= 0 ? appFavorites.getFavorites().indexOf(appIcons[replacingIndex].app) : 0; - let sameApps = this.allowSplitApps ? [] : appIcons.filter(a => a != source && a.app == source.app); - let favoritesCount = 0; - let position = 0; - let interestingWindows = {}; - let getAppWindows = app => { - if (!interestingWindows[app]) { - interestingWindows[app] = AppIcons.getInterestingWindows(app, this.dtpPanel.monitor); - } - - let appWindows = interestingWindows[app]; //prevents "reference to undefined property Symbol.toPrimitive" warning - return appWindows; - }; - - if (sameApps.length && - ((!appIcons[sourceIndex - 1] || appIcons[sourceIndex - 1].app !== source.app) && - (!appIcons[sourceIndex + 1] || appIcons[sourceIndex + 1].app !== source.app))) { - appIcons.splice(appIcons.indexOf(sameApps[0]), sameApps.length); - Array.prototype.splice.apply(appIcons, [sourceIndex + 1, 0].concat(sameApps)); - } - - for (let i = 0, l = appIcons.length; i < l; ++i) { - let windows = []; - - if (!usingLaunchers || (!source.isLauncher && !appIcons[i].isLauncher)) { - windows = appIcons[i].window ? [appIcons[i].window] : getAppWindows(appIcons[i].app); - } - - windows.forEach(w => w._dtpPosition = position++); - - if (this.showFavorites && - ((usingLaunchers && appIcons[i].isLauncher) || - (!usingLaunchers && appFavorites.isFavorite(appIcons[i].app.get_id())))) { - ++favoritesCount; - } - } - - if (sourceIndex < favoritesCount) { - if (appIsFavorite) { - appFavorites.moveFavoriteToPos(sourceAppId, favoriteIndex); - } else { - appFavorites.addFavoriteAtPos(sourceAppId, favoriteIndex); - } - } else if (appIsFavorite && this.showFavorites && (!usingLaunchers || source.isLauncher)) { - appFavorites.removeFavorite(sourceAppId); - } - - appFavorites.emit('changed'); - - return true; - } - - _onShowAppsButtonToggled() { - // Sync the status of the default appButtons. Only if the two statuses are - // different, that means the user interacted with the extension provided - // application button, cutomize the behaviour. Otherwise the shell has changed the - // status (due to the _syncShowAppsButtonToggled function below) and it - // has already performed the desired action. - let selector = SearchController; - - if (selector._showAppsButton && - selector._showAppsButton.checked !== this.showAppsButton.checked) { - // find visible view - - if (this.showAppsButton.checked) { - if (SETTINGS.get_boolean('show-apps-override-escape')) { - //override escape key to return to the desktop when entering the overview using the showapps button - SearchController._onStageKeyPress = function(actor, event) { - if (Main.modalCount == 1 && event.get_key_symbol() === Clutter.KEY_Escape) { - this._searchActive ? this.reset() : Main.overview.hide(); - - return Clutter.EVENT_STOP; - } - - return Object.getPrototypeOf(this)._onStageKeyPress.call(this, actor, event); - }; - - let overviewHiddenId = Main.overview.connect('hidden', () => { - Main.overview.disconnect(overviewHiddenId); - delete SearchController._onStageKeyPress; - }); - } - - // force exiting overview if needed - if (!Main.overview._shown) { - this.forcedOverview = true; - } - - //temporarily use as primary the monitor on which the showapps btn was clicked, this is - //restored by the panel when exiting the overview - this.dtpPanel.panelManager.setFocusedMonitor(this.dtpPanel.monitor); - - // Finally show the overview - selector._showAppsButton.checked = true; - Main.overview.show(2 /*APP_GRID*/); - } - else { - if (this.forcedOverview) { - // force exiting overview if needed - Main.overview.hide(); - } else { - selector._showAppsButton.checked = false; - } - - this.forcedOverview = false; - } - } - } - - _syncShowAppsButtonToggled() { - let status = SearchController._showAppsButton.checked; - if (this.showAppsButton.checked !== status) - this.showAppsButton.checked = status; - } - - showShowAppsButton() { - this.showAppsButton.visible = true; - this.showAppsButton.set_width(-1); - this.showAppsButton.set_height(-1); - } - - popupFocusedAppSecondaryMenu() { - let appIcons = this._getAppIcons(); - let tracker = Shell.WindowTracker.get_default(); - - for(let i in appIcons) { - if(appIcons[i].app == tracker.focus_app) { - let appIcon = appIcons[i]; - if(appIcon._menu && appIcon._menu.isOpen) - appIcon._menu.close(); - else - appIcon.popupMenu(); - - appIcon.sync_hover(); - break; - } - } - } -}; - -const CloneContainerConstraint = GObject.registerClass({ -}, class CloneContainerConstraint extends Clutter.BindConstraint { - - vfunc_update_allocation(actor, actorBox) { - if (!this.source) - return; - - let [stageX, stageY] = this.source.get_transformed_position(); - let [width, height] = this.source.get_transformed_size(); - - actorBox.set_origin(stageX, stageY); - actorBox.set_size(width, height); - } -}); - -export const TaskbarItemContainer = GObject.registerClass({ - -}, class TaskbarItemContainer extends Dash.DashItemContainer { - - _init() { - super._init() - } - - vfunc_allocate(box) { - if (this.child == null) - return; - - this.set_allocation(box); - - let availWidth = box.x2 - box.x1; - let availHeight = box.y2 - box.y1; - let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] = this.child.get_preferred_size(); - let [childScaleX, childScaleY] = this.child.get_scale(); - - let childWidth = Math.min(natChildWidth * childScaleX, availWidth); - let childHeight = Math.min(natChildHeight * childScaleY, availHeight); - let childBox = new Clutter.ActorBox(); - - childBox.x1 = (availWidth - childWidth) / 2; - childBox.y1 = (availHeight - childHeight) / 2; - childBox.x2 = childBox.x1 + childWidth; - childBox.y2 = childBox.y1 + childHeight; - - this.child.allocate(childBox); - } - - // In case appIcon is removed from the taskbar while it is hovered, - // restore opacity before dashItemContainer.animateOutAndDestroy does the destroy animation. - animateOutAndDestroy() { - if (this._raisedClone) { - this._raisedClone.source.opacity = 255; - this._raisedClone.destroy(); - } - - super.animateOutAndDestroy(); - } - - // For ItemShowLabel - _getIconAnimationOffset() { - if (!SETTINGS.get_boolean('animate-appicon-hover')) - return 0; - - let travel = iconAnimationSettings.travel; - let zoom = iconAnimationSettings.zoom; - return this._dtpPanel.dtpSize * (travel + (zoom - 1) / 2); - } - - _updateCloneContainerPosition(cloneContainer) { - let [stageX, stageY] = this.get_transformed_position(); - - cloneContainer.set_position( - stageX - this._dtpPanel.panelBox.translation_x - this.translation_x, - stageY - this._dtpPanel.panelBox.translation_y - this.translation_y - ); - } - - _createRaisedClone() { - let [width, height] = this.get_transformed_size(); - - // "clone" of this child (appIcon actor) - let cloneButton = this.child._delegate.getCloneButton(); - - // "clone" of this (taskbarItemContainer) - let cloneContainer = new St.Bin({ - child: cloneButton, - width: width, height: height, - reactive: false, - }); - - this._updateCloneContainerPosition(cloneContainer); - - // For the stretch animation - let boundProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x'; - this.bind_property(boundProperty, cloneContainer, boundProperty, GObject.BindingFlags.SYNC_CREATE); - - - // The clone follows its source when the taskbar is scrolled. - let taskbarScrollView = this.get_parent().get_parent(); - let adjustment = this._dtpPanel.checkIfVertical() ? taskbarScrollView.vscroll.get_adjustment() : taskbarScrollView.hscroll.get_adjustment(); - let adjustmentChangedId = adjustment.connect('notify::value', () => this._updateCloneContainerPosition(cloneContainer)); - - // Update clone position when an item is added to / removed from the taskbar. - let taskbarBox = this.get_parent(); - let taskbarBoxAllocationChangedId = taskbarBox.connect('notify::allocation', () => this._updateCloneContainerPosition(cloneContainer)); - - // The clone itself - this._raisedClone = cloneButton.child; - this._raisedClone.connect('destroy', () => { - adjustment.disconnect(adjustmentChangedId); - taskbarBox.disconnect(taskbarBoxAllocationChangedId); - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - cloneContainer.destroy(); - return GLib.SOURCE_REMOVE; - }); - delete this._raisedClone; - }); - - this._raisedClone.source.opacity = 0; - Main.uiGroup.add_actor(cloneContainer); - } - - // Animate the clone. - // AppIcon actors cannot go outside the taskbar so the animation is done with a clone. - // If level is zero, the clone is dropped and destroyed. - raise(level) { - if (this._raisedClone) - Utils.stopAnimations(this._raisedClone); - else if (level) - this._createRaisedClone(); - else - return; - - let panelPosition = this._dtpPanel.getPosition(); - let panelElementPositions = this._dtpPanel.panelManager.panelsElementPositions[this._dtpPanel.monitor.index] || Pos.defaults; - let taskbarPosition = panelElementPositions.filter(pos => pos.element == 'taskbar')[0].position; - - let vertical = panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT; - let translationDirection = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT ? 1 : -1; - let rotationDirection; - if (panelPosition == St.Side.LEFT || taskbarPosition == Pos.STACKED_TL) - rotationDirection = -1; - else if (panelPosition == St.Side.RIGHT || taskbarPosition == Pos.STACKED_BR) - rotationDirection = 1; - else { - let items = this.get_parent().get_children(); - let index = items.indexOf(this); - rotationDirection = (index - (items.length - 1) / 2) / ((items.length - 1) / 2); - } - - let duration = iconAnimationSettings.duration / 1000; - let rotation = iconAnimationSettings.rotation; - let travel = iconAnimationSettings.travel; - let zoom = iconAnimationSettings.zoom; - - // level is about 1 for the icon that is hovered, less for others. - // time depends on the translation to do. - let [width, height] = this._raisedClone.source.get_transformed_size(); - let translationMax = (vertical ? width : height) * (travel + (zoom - 1) / 2); - let translationEnd = translationMax * level; - let translationDone = vertical ? this._raisedClone.translation_x : this._raisedClone.translation_y; - let translationTodo = Math.abs(translationEnd - translationDone); - let scale = 1 + (zoom - 1) * level; - let rotationAngleZ = rotationDirection * rotation * level; - let time = duration * translationTodo / translationMax; - - let options = { - scale_x: scale, scale_y: scale, - rotation_angle_z: rotationAngleZ, - time: time, - transition: 'easeOutQuad', - onComplete: () => { - if (!level) { - this._raisedClone.source.opacity = 255; - this._raisedClone.destroy(); - delete this._raisedClone; - } - } - }; - options[vertical ? 'translation_x' : 'translation_y'] = translationDirection * translationEnd; - - Utils.animate(this._raisedClone, options); - } - - // Animate this and cloneContainer, since cloneContainer translation is bound to this. - stretch(translation) { - let duration = iconAnimationSettings.duration / 1000; - let zoom = iconAnimationSettings.zoom; - let animatedProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x'; - let isShowing = this.opacity != 255 || this.child.opacity != 255; - - if (isShowing) { - // Do no stop the animation initiated in DashItemContainer.show. - this[animatedProperty] = zoom * translation; - } else { - let options = { - time: duration, - transition: 'easeOutQuad', - }; - options[animatedProperty] = zoom * translation; - - Utils.stopAnimations(this); - Utils.animate(this, options); - } - } -}); - -const DragPlaceholderItem = GObject.registerClass({ -}, class DragPlaceholderItem extends St.Widget { - - _init(appIcon, iconSize, isVertical) { - super._init({ style: AppIcons.getIconContainerStyle(isVertical), layout_manager: new Clutter.BinLayout() }); - - this.child = { _delegate: appIcon }; - - this._clone = new Clutter.Clone({ - source: appIcon.icon._iconBin, - width: iconSize, - height: iconSize - }); - - this.add_actor(this._clone); - } - - destroy() { - this._clone.destroy(); - super.destroy(); - } -}); - -export function getAppStableSequence(app, monitor) { - let windows = AppIcons.getInterestingWindows(app, monitor); - - return windows.reduce((prevWindow, window) => { - return Math.min(prevWindow, getWindowStableSequence(window)); - }, Infinity); -} - -export function sortWindowsCompareFunction(windowA, windowB) { - return getWindowStableSequence(windowA) - getWindowStableSequence(windowB); -} - -export function getWindowStableSequence(window) { - return ('_dtpPosition' in window ? window._dtpPosition : window.get_stable_sequence()); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/transparency.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/transparency.js deleted file mode 100644 index 25ff00f..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/transparency.js +++ /dev/null @@ -1,252 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -import GdkPixbuf from 'gi://GdkPixbuf'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import St from 'gi://St'; - -import * as Proximity from './proximity.js'; -import * as Utils from './utils.js'; -import {SETTINGS} from './extension.js'; - -export const DynamicTransparency = class { - - constructor(dtpPanel) { - this._dtpPanel = dtpPanel; - this._proximityManager = dtpPanel.panelManager.proximityManager; - this._proximityWatchId = 0; - this.currentBackgroundColor = 0; - - this._initialPanelStyle = dtpPanel.panel.get_style(); - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._bindSignals(); - - this._updateAnimationDuration(); - this._updateAllAndSet(); - this._updateProximityWatch(); - } - - destroy() { - this._signalsHandler.destroy(); - this._proximityManager.removeWatch(this._proximityWatchId); - - this._dtpPanel.panel.set_style(this._initialPanelStyle); - } - - updateExternalStyle() { - this._updateComplementaryStyles(); - this._setBackground(); - } - - _bindSignals() { - this._signalsHandler.add( - [ - Utils.getStageTheme(), - 'changed', - () => this._updateAllAndSet() - ], - [ - Main.overview, - [ - 'showing', - 'hiding' - ], - () => this._updateAlphaAndSet() - ], - [ - SETTINGS, - [ - 'changed::trans-use-custom-bg', - 'changed::trans-bg-color' - ], - () => this._updateColorAndSet() - ], - [ - SETTINGS, - [ - 'changed::trans-use-custom-opacity', - 'changed::trans-panel-opacity', - 'changed::trans-bg-color', - 'changed::trans-dynamic-anim-target', - 'changed::trans-use-dynamic-opacity' - ], - () => this._updateAlphaAndSet() - ], - [ - SETTINGS, - [ - 'changed::trans-use-custom-gradient', - 'changed::trans-gradient-top-color', - 'changed::trans-gradient-bottom-color', - 'changed::trans-gradient-top-opacity', - 'changed::trans-gradient-bottom-opacity' - ], - () => this._updateGradientAndSet() - ], - [ - SETTINGS, - [ - 'changed::trans-dynamic-behavior', - 'changed::trans-use-dynamic-opacity', - 'changed::trans-dynamic-distance' - ], - () => this._updateProximityWatch() - ], - [ - SETTINGS, - 'changed::trans-dynamic-anim-time', - () => this._updateAnimationDuration() - ] - ); - } - - _updateProximityWatch() { - this._proximityManager.removeWatch(this._proximityWatchId); - - if (SETTINGS.get_boolean('trans-use-dynamic-opacity')) { - let isVertical = this._dtpPanel.checkIfVertical(); - let threshold = SETTINGS.get_int('trans-dynamic-distance'); - - this._windowOverlap = false; - this._updateAlphaAndSet() - - this._proximityWatchId = this._proximityManager.createWatch( - this._dtpPanel.panelBox.get_parent(), - this._dtpPanel.monitor.index, - Proximity.Mode[SETTINGS.get_string('trans-dynamic-behavior')], - isVertical ? threshold : 0, - isVertical ? 0 : threshold, - overlap => { - this._windowOverlap = overlap; - this._updateAlphaAndSet(); - } - ); - } - } - - _updateAnimationDuration() { - this.animationDuration = (SETTINGS.get_int('trans-dynamic-anim-time') * 0.001) + 's;'; - } - - _updateAllAndSet() { - let themeBackground = this._getThemeBackground(true); - - this._updateColor(themeBackground); - this._updateAlpha(themeBackground); - this._updateComplementaryStyles(); - this._updateGradient(); - this._setBackground(); - this._setGradient(); - } - - _updateColorAndSet() { - this._updateColor(); - this._setBackground(); - } - - _updateAlphaAndSet() { - this._updateAlpha(); - this._setBackground(); - } - - _updateGradientAndSet() { - this._updateGradient(); - this._setGradient(); - } - - _updateComplementaryStyles() { - let panelThemeNode = this._dtpPanel.panel.get_theme_node(); - - this._complementaryStyles = 'border-radius: ' + panelThemeNode.get_border_radius(0) + 'px;'; - } - - _updateColor(themeBackground) { - this.backgroundColorRgb = SETTINGS.get_boolean('trans-use-custom-bg') ? - SETTINGS.get_string('trans-bg-color') : - (themeBackground || this._getThemeBackground()); - } - - _updateAlpha(themeBackground) { - if (this._windowOverlap && !Main.overview.visibleTarget && SETTINGS.get_boolean('trans-use-dynamic-opacity')) { - this.alpha = SETTINGS.get_double('trans-dynamic-anim-target'); - } else { - this.alpha = SETTINGS.get_boolean('trans-use-custom-opacity') ? - SETTINGS.get_double('trans-panel-opacity') : - (themeBackground || this._getThemeBackground()).alpha * 0.003921569; // 1 / 255 = 0.003921569 - } - } - - _updateGradient() { - this._gradientStyle = ''; - - if (SETTINGS.get_boolean('trans-use-custom-gradient')) { - this._gradientStyle += 'background-gradient-direction: ' + (this._dtpPanel.checkIfVertical() ? 'horizontal;' : 'vertical;') + - 'background-gradient-start: ' + Utils.getrgbaColor(SETTINGS.get_string('trans-gradient-top-color'), - SETTINGS.get_double('trans-gradient-top-opacity')) + - 'background-gradient-end: ' + Utils.getrgbaColor(SETTINGS.get_string('trans-gradient-bottom-color'), - SETTINGS.get_double('trans-gradient-bottom-opacity')); - } - } - - _setBackground() { - this.currentBackgroundColor = Utils.getrgbaColor(this.backgroundColorRgb, this.alpha); - - let transition = 'transition-duration:' + this.animationDuration; - - this._dtpPanel.set_style('background-color: ' + this.currentBackgroundColor + transition + this._complementaryStyles); - } - - _setGradient() { - this._dtpPanel.panel.set_style( - 'background: none; ' + - 'border-image: none; ' + - 'background-image: none; ' + - this._gradientStyle + - 'transition-duration:' + this.animationDuration - ); - } - - _getThemeBackground(reload) { - if (reload || !this._themeBackground) { - let fakePanel = new St.Bin({ name: 'panel' }); - Main.uiGroup.add_child(fakePanel); - let fakeTheme = fakePanel.get_theme_node() - this._themeBackground = this._getBackgroundImageColor(fakeTheme) || fakeTheme.get_background_color(); - Main.uiGroup.remove_child(fakePanel); - } - - return this._themeBackground; - } - - _getBackgroundImageColor(theme) { - let bg = null; - - try { - let imageFile = theme.get_background_image() || theme.get_border_image().get_file(); - - if (imageFile) { - let imageBuf = GdkPixbuf.Pixbuf.new_from_file(imageFile.get_path()); - let pixels = imageBuf.get_pixels(); - - bg = { red: pixels[0], green: pixels[1], blue: pixels[2], alpha: pixels[3] }; - } - } catch (error) {} - - return bg; - } -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAdvancedOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAdvancedOptions.ui deleted file mode 100644 index 3007d95..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAdvancedOptions.ui +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Nothing yet! - For real... - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAnimateAppIconHoverOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAnimateAppIconHoverOptions.ui deleted file mode 100644 index f49e2d7..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxAnimateAppIconHoverOptions.ui +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - 0 - 300 - 1 - 5 - - - - -30 - 30 - 1 - 5 - - - - 0 - 100 - 1 - 5 - - - - 100 - 250 - 1 - 5 - - - - 0 - 3 - 0.1 - 1 - - - - 1 - 10 - 0.1 - 1 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Animation type - - - center - - Simple - Ripple - Plank - - - - - - - - - - - - - - - Duration - - - center - 300 - animate_appicon_hover_options_duration_adjustment - 0 - 0 - right - True - - - - - - - - Rotation - - - end - 300 - animate_appicon_hover_options_rotation_adjustment - 0 - 0 - right - True - - - - - - - - Travel - - - center - 300 - animate_appicon_hover_options_travel_adjustment - 0 - 0 - right - True - - - - - - - - Zoom - - - center - 300 - animate_appicon_hover_options_zoom_adjustment - 0 - 0 - right - True - - - - - - - - Convexity - - - end - 300 - animate_appicon_hover_options_convexity_adjustment - 1 - 1 - right - True - - - - - - - - Extent - - - center - 300 - animate_appicon_hover_options_extent_adjustment - 0 - 0 - right - True - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDotOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDotOptions.ui deleted file mode 100644 index 18c81ec..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDotOptions.ui +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - 5 - 100 - 5 - 5 - - - - 5 - 1 - 5 - - - - 600 - 600 - True - - - - vertical - 24 - 32 - 32 - 32 - 32 - - - - - - - Highlight focused application - - - center - - - - - - - - - - - - - - Icon dominant color - - - center - - - - - - - - Custom color - - - center - - - - - - - - Highlight opacity - - - center - 5 - focus_highlight_opacity_adjustment - 5 - - - - - - - - - - - - - - Indicator size (px) - - - center - 0 - dot_size_adjustment - - - - - - - - Indicator color - Icon Dominant - - - center - - - - - - - - - - - - - - Indicator color - Override Theme - - - center - - - - - - - - - - - - - 1 window open (or ungrouped) - - - center - Apply to all - - - - - center - - - - - - - - 2 windows open - - - center - - - - - - - - 3 windows open - - - center - - - - - - - - 4+ windows open - - - center - - - - - - - - - - - - - - Use different for unfocused - - - center - - - - - - - - - - - - - - 1 window open (or ungrouped) - - - center - Apply to all - - - - - center - - - - - - - - 2 windows open - - - center - - - - - - - - 3 windows open - - - center - - - - - - - - 4+ windows open - - - center - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDynamicOpacityOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDynamicOpacityOptions.ui deleted file mode 100644 index 447f50d..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxDynamicOpacityOptions.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - 200 - 1 - 10 - - - - 100 - 5 - 10 - - - - 2000 - 1 - 10 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - The panel background opacity is affected by - - - center - - All windows - Focused windows - Maximized windows - - - - - - - - - Change opacity when a window gets closer than (px) - - - center - 4 - 50 - trans_distance_adjustment - True - 50 - - - - - - - - Change opacity to (%) - - - 0 - center - trans_opacity_min_adjustment - - - - - - - - Opacity change animation duration (ms) - - - 4 - 50 - center - trans_anim_time_adjustment - True - 50 - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxGroupAppsOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxGroupAppsOptions.ui deleted file mode 100644 index ffc4d90..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxGroupAppsOptions.ui +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - 6 - 24 - 1 - 100 - - - - 1000 - 10 - 100 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Font size (px) of the application titles (default is 14) - - - center - 4 - 0 - group_apps_label_font_size_adjustment - True - - - - - - - - Font weight of application titles - - - center - - inherit from theme - normal - lighter - bold - bolder - - - - - - - - - Font color of the application titles - - - True - center - - - - - - - - Font color of the minimized application titles - - - True - center - - - - - - - - - - - - - - Maximum width (px) of the application titles - (default is 160) - - - center - 4 - 0 - group_apps_label_max_width_adjustment - True - - - - - - - - Use a fixed width for the application titles - The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width. - - - center - - - - - - - - - - - - - - Display running indicators on unfocused applications - - - center - - - - - - - - Use the favorite icons as application launchers - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxIntellihideOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxIntellihideOptions.ui deleted file mode 100644 index a60dab3..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxIntellihideOptions.ui +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - 1 - 9990 - 10 - 100 - - - - 1 - 5000 - 10 - 100 - - - - 10 - 2000 - 10 - 100 - - - - 10 - 4000 - 10 - 100 - - - - 10000 - 10 - 100 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Only hide the panel when it is obstructed by windows - - - center - - - - - - - - The panel hides from - - - center - - All windows - Focused windows - Maximized windows - - - - - - - - - - - - - - - Require pressure at the edge of the screen to reveal the panel - - - center - - - - - - - - Required pressure threshold (px) - - - center - 4 - 0 - intellihide_pressure_threshold_adjustment - True - - - - - - - - Required pressure timeout (ms) - - - center - 4 - 0 - intellihide_pressure_time_adjustment - True - - - - - - - - - - - - - - Allow the panel to be revealed while in fullscreen mode - - - center - - - - - - - - Only hide secondary panels - (requires multi-monitors option) - - - center - - - - - - - - Keyboard shortcut to reveal and hold the panel - Syntax: <Shift>, <Ctrl>, <Alt>, <Super> - - - center - 12 - e.g. <Super>i - - - - - - - - - - - - - - Hide and reveal animation duration (ms) - - - center - 4 - 0 - intellihide_animation_time_adjustment - True - - - - - - - - Delay before hiding the panel (ms) - - - center - 4 - 10 - intellihide_close_delay_adjustment - True - 10 - - - - - - - - Delay before enabling intellihide on start (ms) - - - center - 4 - 10 - intellihide_enable_hide_delay_adjustment - True - 10 - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxMiddleClickOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxMiddleClickOptions.ui deleted file mode 100644 index 023845e..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxMiddleClickOptions.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Shift+Click action - When set to minimize, double clicking minimizes all the windows of the application. - - - center - - Raise windows - Minimize window - Launch new instance - Cycle through windows - Cycle windows + minimize - Toggle single / Preview multiple - Toggle single / Cycle multiple - Quit - - - - - - - - - - - - - - - Middle-Click action - Behavior for Middle-Click. - - - center - - Raise windows - Minimize window - Launch new instance - Cycle through windows - Cycle windows + minimize - Toggle single / Preview multiple - Toggle single / Cycle multiple - Quit - - - - - - - - - - - - - - - Shift+Middle-Click action - Behavior for Shift+Middle-Click. - - - center - - Raise windows - Minimize window - Launch new instance - Cycle through windows - Cycle windows + minimize - Toggle single / Preview multiple - Toggle single / Cycle multiple - Quit - - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxOverlayShortcut.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxOverlayShortcut.ui deleted file mode 100644 index 98fcb0a..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxOverlayShortcut.ui +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - 10000 - 250 - 1000 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Hotkeys prefix - Hotkeys will either be Super+Number or Super+Alt+Num - - - center - - Super - Super + Alt - - - - - - - - - Number overlay - Temporarily show the application numbers over the icons when using the hotkeys. - - - center - - Never - Show temporarily - Always visible - - - - - - - - - Hide timeout (ms) - - - center - shortcut_time_adjustment - - - - - - - - Shortcut to show the overlay for 2 seconds - Syntax: <Shift>, <Ctrl>, <Alt>, <Super> - - - center - 12 - e.g. <Super>q - - - - - - - - Show window previews on hotkey - Show previews when the application have multiple instances - - - center - - - - - - - - Hotkeys are activated with - Select which keyboard number keys are used to activate the hotkeys - - - center - - Number row - Numeric keypad - Both - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollIconOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollIconOptions.ui deleted file mode 100644 index bb457ff..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollIconOptions.ui +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - 2000 - 10 - 50 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Delay between mouse scroll events (ms) - Use this value to limit the number of captured mouse scroll events. - - - center - 4 - 50 - scroll_icon_options_delay_adjustment - True - 50 - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollPanelOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollPanelOptions.ui deleted file mode 100644 index 2354b76..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxScrollPanelOptions.ui +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - 2000 - 10 - 50 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Delay between mouse scroll events (ms) - Use this value to limit the number of captured mouse scroll events. - - - center - 4 - 50 - scroll_panel_options_delay_adjustment - True - 50 - - - - - - - - Show popup when changing workspace - This affects workspace popup when scrolling on the panel only. - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxSecondaryMenuOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxSecondaryMenuOptions.ui deleted file mode 100644 index 483ddc8..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxSecondaryMenuOptions.ui +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Integrate <i>AppMenu</i> items - - - center - - - - - - - - <i>Show Details</i> menu item - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowApplicationsOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowApplicationsOptions.ui deleted file mode 100644 index ee183a5..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowApplicationsOptions.ui +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - 100 - 1 - 10 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Show Applications icon - - - 32 - 32 - gtk-missing-image - 32 - - - - - - - - - - 8 - 8 - 8 - 8 - 140 - True - - - - - - - - - - - - - - Show Applications icon side padding (px) - - - center - 0 - show_applications_side_padding_adjustment - - - - - - - - Override escape key and return to desktop - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowDesktopOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowDesktopOptions.ui deleted file mode 100644 index be5d21c..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxShowDesktopOptions.ui +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - 1 - 40 - 1 - 10 - - - - 5000 - 10 - 100 - - - - 5000 - 10 - 100 - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - - - center - 4 - 1 - show_showdesktop_width_adjustment - True - 1 - - - - - - - - Override Show Desktop line color - - > - True - center - True - - - - - center - - - - - - - - - - - - - - Reveal the desktop when hovering the Show Desktop button - - - True - end - center - - - - - - - - Delay before revealing the desktop (ms) - - - center - 4 - 1 - show_showdesktop_delay_adjustment - True - 1 - - - - - - - - Fade duration (ms) - - - center - 4 - 1 - show_showdesktop_time_adjustment - True - 1 - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxWindowPreviewOptions.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxWindowPreviewOptions.ui deleted file mode 100644 index 87cecff..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/BoxWindowPreviewOptions.ui +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - 9999 - 25 - 100 - - - - 1000 - 10 - 50 - - - - 9999 - 25 - 100 - - - - 100 - 800 - 10 - 50 - - - - 50 - 1 - 5 - - - - 100 - 5 - 10 - - - - 8 - 48 - 1 - 100 - - - - 6 - 24 - 1 - 100 - - - - 50 - 9999 - 25 - 100 - - - - 255 - 10 - 25 - - - - 800 - 600 - True - - - - vertical - 600 - 24 - 32 - 32 - 32 - 32 - - - - - - - Time (ms) before showing - (400 is default) - - - center - 4 - 0 - preview_timeout_adjustment - True - - - - - - - - Time (ms) before hiding - (100 is default) - - - False - - - 4 - Immediate on application icon click - True - - - - - - - center - 4 - 25 - leave_timeout_adjustment - True - 25 - - - - - - - - Animation time (ms) - - - center - 4 - 0 - preview_animation_time_adjustment - True - - - - - - - - - - - - - - Middle click on the preview to close the window - - - center - - - - - - - - - - - - - - Window previews preferred size (px) - - - center - 4 - 100 - preview_size_adjustment - True - 100 - - - - - - - - Window previews aspect ratio X (width) - - - center - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21 - - - - - - Fixed - True - center - - - - - - - - Window previews aspect ratio Y (height) - - - center - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21 - - - - - - Fixed - True - center - - - - - - - - Window previews padding (px) - - - center - 4 - 50 - preview_padding_adjustment - True - 50 - - - - - - - - - - - - - - Use custom opacity for the previews background - If disabled, the previews background have the same opacity as the panel. - - - center - - - - - center - 5 - preview_opacity_adjustment - 5 - - - - - - - - - - - - - - Close button and header position - - - Bottom - False - center - True - - - - - - Top - False - center - preview_title_position_bottom_button - - - - - - - - - - - - - - - Display window preview headers - - > - center - - - - - - - - Icon size (px) of the window preview - If disabled, the previews icon size will be based on headerbar size - - - center - - - - - center - 4 - 6 - preview_custom_icon_size_adjustment - True - 6 - - - - - - - - Font size (px) of the preview titles - - - center - 4 - 6 - preview_title_font_size_adjustment - True - 6 - - - - - - - - Font weight of the preview titles - - - center - - inherit from theme - normal - lighter - bold - bolder - - - - - - - - - Font color of the preview titles - - - True - center - - - - - - - - - - - - - - Enable window peeking - When hovering over a window preview for some time, the window gets distinguished. - - - center - - - - - - - - Enter window peeking mode timeout (ms) - Time of inactivity while hovering over a window preview needed to enter the window peeking mode. - - - center - 4 - 50 - enter_peek_mode_timeout_adjustment - True - 50 - - - - - - - - Window peeking mode opacity - All windows except for the peeked one have their opacity set to the same value. - - - center - 4 - 0 - peek_mode_opacity_adjustment - True - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAbout.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAbout.ui deleted file mode 100644 index f7dec72..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAbout.ui +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - About - help-about-symbolic - - - - - Info - - - - Version - - - ... - - - - - - - - Source - - - GitHub - True - center - https://github.com/home-sweet-gnome/dash-to-panel - - - - - - - - - - - - Export and Import - - - - Export and import settings - Use the buttons below to create a settings file from your current preferences that can be imported on a different machine. - - - - - - - - 8 - 8 - 4 - 4 - 8 - end - - - Export to file - True - - - - - Import from file - True - - - - - - - - - - - - - - - - <span size="small">This program comes with ABSOLUTELY NO WARRANTY. See the <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2 or later</a> for details.</span> - True - center - True - - - - - - - diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAction.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAction.ui deleted file mode 100644 index b22053f..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsAction.ui +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - Action - view-pin-symbolic - - - - - Click action - - - - Click action - Behaviour when clicking on the icon of a running application. - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - Cycle windows + minimize - Cycle through windows - Toggle single / Preview multiple - Toggle single / Cycle multiple - Toggle windows - Raise windows - Launch new instance - - - - - - - - - - - - - Scroll action - - - - Scroll panel action - Behavior when mouse scrolling over the panel. - - - True - True - end - center - - - True - emblem-system-symbolic - - - - - - - - True - center - True - - Do nothing - Switch workspace - Cycle windows - Change volume - - - - - - - - - Scroll icon action - Behavior when mouse scrolling over an application icon. - - - True - center - - - True - emblem-system-symbolic - - - - - - - - center - True - - Do nothing - Cycle windows - Same as panel - - - - - - - - - - - - - Hotkey overlay - - - - Use hotkeys to activate apps - Enable Super+(0-9) as shortcuts to activate apps. It can also be used together with Shift and Ctrl. - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsBehavior.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsBehavior.ui deleted file mode 100644 index 677f38a..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsBehavior.ui +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Behavior - preferences-system-symbolic - - - - - Applications - - - - Show favorite applications - - - center - - - - - - - - Show favorite applications on secondary panels - - - center - - - - - - - - Show running applications - - - center - - - - - - - - Ungroup applications - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - Show notification counter badge - - - True - end - center - - - - - - - - - - - - Hover - - - - Show window previews on hover - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - Show tooltip on hover - - - center - - - - - - - - - - - - Isolate - - - - Isolate Workspaces - - - center - - - - - - - - Isolate monitors - - - center - - - - - - - - - - - - Overview - - - - Click empty space to close overview - - - center - - - - - - - - Disable show overview on startup - - - center - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsFineTune.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsFineTune.ui deleted file mode 100644 index 5306ec5..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsFineTune.ui +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 0.33 - 1 - 0.01 - 0.1 - - - - Fine-Tune - preferences-other-symbolic - - - - - Font size - - - - Tray Font Size - (0 = theme default) - - - 300 - tray_size_adjustment - 0 - 0 - right - True - - - - - - - - - LeftBox Font Size - (0 = theme default) - - - 300 - leftbox_size_adjustment - 0 - 0 - right - True - - - - - - - - - - - - - Padding - - - - Tray Item Padding - (-1 = theme default) - - - 300 - tray_padding_adjustment - 0 - 0 - right - True - - - - - - - - - Status Icon Padding - (-1 = theme default) - - - 300 - statusicon_padding_adjustment - 0 - 0 - right - True - - - - - - - - - LeftBox Padding - (-1 = theme default) - - - 300 - leftbox_padding_adjustment - 0 - 0 - right - True - - - - - - - - - - - - - Animate - - - - Animate switching applications - - - center - - - - - - - - Animate launching new windows - - - center - - - - - - - - - - - - Gnome functionality - - - - Keep original gnome-shell dash - (overview) - - - center - - - - - - - - Keep original gnome-shell top panel - - - center - - - - - - - - Activate panel menu buttons on click only - (e.g. date menu) - - - center - - - - - - - - Force Activities hot corner on primary monitor - - - center - - - - - - - - - - - - - - - App icon secondary menu - (right-click menu) - - - True - center - - - emblem-system-symbolic - - - - - - - - - - - - - - - - - - Advanced Options - False - True - end - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsPosition.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsPosition.ui deleted file mode 100644 index b7a1b31..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsPosition.ui +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 100 - 1 - 10 - - - - Position - find-location-symbolic - - - - - Panel - - - - Display the main panel on - - - center - - - - - - - - Display panels on all monitors - - - center - - - - - - - - - - - - - Panel Intellihide - Hide and reveal the panel according to preferences - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - - - - - Order and Position on monitors - - - - - Monitor - - - 6 - 6 - 6 - 6 - - - Apply changes to all monitors - False - start - True - - - - - end - center - True - - - - - - - - - - - - - - - - - Panel screen position - - - Bottom - False - center - True - - - - - - Top - False - center - position_bottom_button - - - - - - Left - False - center - position_bottom_button - - - - - - Right - False - center - position_bottom_button - - - - - - - - - Panel thickness - (default is 48) - - - 300 - panel_size_adjustment - 0 - 0 - right - True - - - - - - - - - Panel length (%) - (default is 100) - - - 300 - panel_length_adjustment - 0 - 0 - right - True - - - - - - - - Anchor - - - center - - Start - Middle - End - - - - - - - - - - - - - - - - Taskbar Display - - - 6 - 6 - True - none - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsStyle.ui b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsStyle.ui deleted file mode 100644 index 6de94b8..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/ui/SettingsStyle.ui +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 0.33 - 1 - 0.01 - 0.1 - - - - 100 - 5 - 10 - - - - 100 - 5 - 10 - - - - 100 - 5 - 10 - - - - Style - applications-graphics-symbolic - - - - - AppIcon style - - - - App Icon Margin - (default is 8) - - - 300 - appicon_margin_adjustment - 0 - 0 - right - True - - - - - - - - - App Icon Padding - (default is 4) - - - 300 - appicon_padding_adjustment - 0 - 0 - right - True - - - - - - - - - Animate hovering app icons - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - - - - - Running indicator - - - - Running indicator position - - - Bottom - center - - - - - - Top - center - dots_bottom_button - - - - - - Left - center - dots_bottom_button - - - - - - Right - center - dots_bottom_button - - - - - - - - - Running indicator style (Focused app) - - - center - - - emblem-system-symbolic - - - - - - - - center - - Dots - Squares - Dashes - Segmented - Solid - Ciliora - Metro - - - - - - - - - Running indicator style (Unfocused apps) - - - center - - Dots - Squares - Dashes - Segmented - Solid - Ciliora - Metro - - - - - - - - - - - - - Panel style - - - - Override panel theme background color - - - center - - - - - center - - - - - - - - - - - - - - Override panel theme background opacity - - - center - - - - - - - - Panel background opacity (%) - - - center - 0 - trans_opacity_adjustment - - - - - - - - Dynamic background opacity - Change opacity when a window gets close to the panel - - - True - center - - - emblem-system-symbolic - - - - - - - - center - - - - - - - - - - - - - - - Override panel theme gradient - - - center - - - - - - - - Gradient top color and opacity (%) - - - True - center - - - - - center - 0 - trans_gradient_opacity1_adjustment - - - - - - - - Gradient bottom color and opacity (%) - - - True - center - - - - - center - 0 - trans_gradient_opacity2_adjustment - - - - - - - - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/utils.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/utils.js deleted file mode 100644 index 8fa2986..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/utils.js +++ /dev/null @@ -1,883 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - * - * - * Credits: - * This file is based on code from the Dash to Dock extension by micheleg - * and code from the Taskbar extension by Zorin OS - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import Clutter from 'gi://Clutter'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Graphene from 'gi://Graphene'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; - -const SCROLL_TIME = Util.SCROLL_TIME / (Util.SCROLL_TIME > 1 ? 1000 : 1); - -// simplify global signals and function injections handling -// abstract class -export const BasicHandler = class { - - constructor() { - this._storage = new Object(); - } - - add(/*unlimited 3-long array arguments*/){ - - // convert arguments object to array, concatenate with generic - let args = [].concat('generic', [].slice.call(arguments)); - // call addWithLabel with ags as if they were passed arguments - this.addWithLabel.apply(this, args); - } - - destroy() { - for( let label in this._storage ) - this.removeWithLabel(label); - } - - addWithLabel( label /* plus unlimited 3-long array arguments*/) { - - if(this._storage[label] == undefined) - this._storage[label] = new Array(); - - // skip first element of the arguments - for( let i = 1; i < arguments.length; i++ ) { - let item = this._storage[label]; - let handlers = this._create(arguments[i]); - - for (let j = 0, l = handlers.length; j < l; ++j) { - item.push(handlers[j]); - } - } - - } - - removeWithLabel(label){ - - if(this._storage[label]) { - for( let i = 0; i < this._storage[label].length; i++ ) { - this._remove(this._storage[label][i]); - } - - delete this._storage[label]; - } - } - - /* Virtual methods to be implemented by subclass */ - // create single element to be stored in the storage structure - _create(item){ - throw new Error('no implementation of _create in ' + this); - } - - // correctly delete single element - _remove(item){ - throw new Error('no implementation of _remove in ' + this); - } -} - -// Manage global signals -export const GlobalSignalsHandler = class extends BasicHandler { - - _create(item) { - let handlers = []; - - item[1] = [].concat(item[1]); - - for (let i = 0, l = item[1].length; i < l; ++i) { - let object = item[0]; - let event = item[1][i]; - let callback = item[2] - try { - let id = object.connect(event, callback); - - handlers.push([object, id]); - } catch (e) - { - - } - } - - return handlers; - } - - _remove(item){ - item[0].disconnect(item[1]); - } -}; - -/** - * Manage function injection: both instances and prototype can be overridden - * and restored - */ -export const InjectionsHandler = class extends BasicHandler { - - _create(item) { - let object = item[0]; - let name = item[1]; - let injectedFunction = item[2]; - let original = object[name]; - - object[name] = injectedFunction; - return [[object, name, injectedFunction, original]]; - } - - _remove(item) { - let object = item[0]; - let name = item[1]; - let original = item[3]; - object[name] = original; - } -}; - -/** - * Manage timeouts: the added timeouts have their id reset on completion - */ -export const TimeoutsHandler = class extends BasicHandler { - - _create(item) { - let name = item[0]; - let delay = item[1]; - let timeoutHandler = item[2]; - - this._remove(item); - - this[name] = GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, () => { - this[name] = 0; - timeoutHandler(); - - return GLib.SOURCE_REMOVE; - }); - - return [[name]]; - } - - remove(name) { - this._remove([name]) - } - - _remove(item) { - let name = item[0]; - - if (this[name]) { - GLib.Source.remove(this[name]); - this[name] = 0; - } - } - - getId(name) { - return this[name] ? this[name] : 0; - } -}; - -// This is wrapper to maintain compatibility with GNOME-Shell 3.30+ as well as -// previous versions. -export const DisplayWrapper = { - getScreen() { - return global.screen || global.display; - }, - - getWorkspaceManager() { - return global.screen || global.workspace_manager; - }, - - getMonitorManager() { - return global.screen || global.backend.get_monitor_manager(); - } -}; - -let unredirectEnabled = true -export const setDisplayUnredirect = (enable) => { - if (enable && !unredirectEnabled) - Meta.enable_unredirect_for_display(global.display); - else if (!enable && unredirectEnabled) - Meta.disable_unredirect_for_display(global.display); - - unredirectEnabled = enable; -}; - -export const getSystemMenuInfo = function() { - return { - name: 'quickSettings', - constructor: Main.panel.statusArea.quickSettings.constructor - }; -} - -export const getCurrentWorkspace = function() { - return DisplayWrapper.getWorkspaceManager().get_active_workspace(); -}; - -export const getWorkspaceByIndex = function(index) { - return DisplayWrapper.getWorkspaceManager().get_workspace_by_index(index); -}; - -export const getWorkspaceCount = function() { - return DisplayWrapper.getWorkspaceManager().n_workspaces; -}; - -export const getStageTheme = function() { - return St.ThemeContext.get_for_stage(global.stage); -}; - -export const getScaleFactor = function() { - return getStageTheme().scale_factor || 1; -}; - -export const findIndex = function(array, predicate) { - if (array) { - if (Array.prototype.findIndex) { - return array.findIndex(predicate); - } - - for (let i = 0, l = array.length; i < l; ++i) { - if (predicate(array[i])) { - return i; - } - } - } - - return -1; -}; - -export const find = function(array, predicate) { - let index = findIndex(array, predicate); - - if (index > -1) { - return array[index]; - } -}; - -export const mergeObjects = function(main, bck) { - for (const prop in bck) { - if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) { - main[prop] = bck[prop]; - } - } - - return main; -}; - -export const getTrackedActorData = (actor) => { - let trackedIndex = Main.layoutManager._findActor(actor); - - if (trackedIndex >= 0) - return Main.layoutManager._trackedActors[trackedIndex] -} - -export const getTransformedAllocation = function(actor) { - let extents = actor.get_transformed_extents(); - let topLeft = extents.get_top_left(); - let bottomRight = extents.get_bottom_right(); - - return { x1: topLeft.x, x2: bottomRight.x, y1: topLeft.y, y2: bottomRight.y }; -}; - -export const setClip = function(actor, x, y, width, height) { - actor.set_clip(0, 0, width, height); - actor.set_position(x, y); - actor.set_size(width, height); -}; - -export const addKeybinding = function(key, settings, handler, modes) { - if (!Main.wm._allowedKeybindings[key]) { - Main.wm.addKeybinding( - key, - settings, - Meta.KeyBindingFlags.NONE, - modes || (Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW), - handler - ); - } -}; - -export const removeKeybinding = function(key) { - if (Main.wm._allowedKeybindings[key]) { - Main.wm.removeKeybinding(key); - } -}; - -export const getrgbColor = function(color) { - color = typeof color === 'string' ? Clutter.color_from_string(color)[1] : color; - - return { red: color.red, green: color.green, blue: color.blue }; -}; - -export const getrgbaColor = function(color, alpha, offset) { - if (alpha <= 0) { - return 'transparent; '; - } - - let rgb = getrgbColor(color); - - if (offset) { - ['red', 'green', 'blue'].forEach(k => { - rgb[k] = Math.min(255, Math.max(0, rgb[k] + offset)); - - if (rgb[k] == color[k]) { - rgb[k] = Math.min(255, Math.max(0, rgb[k] - offset)); - } - }); - } - - return 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ',' + (Math.floor(alpha * 100) * 0.01) + '); ' ; -}; - -export const checkIfColorIsBright = function(color) { - let rgb = getrgbColor(color); - let brightness = 0.2126 * rgb.red + 0.7152 * rgb.green + 0.0722 * rgb.blue; - - return brightness > 128; -}; - -export const getMouseScrollDirection = function(event) { - let direction; - - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - case Clutter.ScrollDirection.LEFT: - direction = 'up'; - break; - case Clutter.ScrollDirection.DOWN: - case Clutter.ScrollDirection.RIGHT: - direction = 'down'; - break; - } - - return direction; -}; - -export const checkIfWindowHasTransient = function(window) { - let hasTransient; - - window.foreach_transient(t => !(hasTransient = true)); - - return hasTransient; -}; - -export const activateSiblingWindow = function(windows, direction, startWindow) { - let windowIndex = windows.indexOf(global.display.focus_window); - let nextWindowIndex = windowIndex < 0 ? - startWindow ? windows.indexOf(startWindow) : 0 : - windowIndex + (direction == 'up' ? -1 : 1); - - if (nextWindowIndex == windows.length) { - nextWindowIndex = 0; - } else if (nextWindowIndex < 0) { - nextWindowIndex = windows.length - 1; - } - - if (windowIndex != nextWindowIndex) { - Main.activateWindow(windows[nextWindowIndex]); - } -}; - -export const animateWindowOpacity = function(window, tweenOpts) { - //there currently is a mutter bug with the windowactor opacity, starting with 3.34 - //https://gitlab.gnome.org/GNOME/mutter/issues/836 - - //since 3.36, a workaround is to use the windowactor's child for the fade animation - //this leaves a "shadow" on the desktop, so the windowactor needs to be hidden - //when the animation is complete - let visible = tweenOpts.opacity > 0; - let windowActor = window; - let initialOpacity = window.opacity; - - window = windowActor.get_first_child() || windowActor; - - if (!windowActor.visible && visible) { - window.opacity = 0; - windowActor.visible = visible; - tweenOpts.opacity = Math.min(initialOpacity, tweenOpts.opacity); - } - - if (!visible) { - tweenOpts.onComplete = () => { - windowActor.visible = visible; - window.opacity = initialOpacity; - }; - } - - animate(window, tweenOpts); -}; - -export const animate = function(actor, options) { - //the original animations used Tweener instead of Clutter animations, so we - //use "time" and "delay" properties defined in seconds, as opposed to Clutter - //animations "duration" and "delay" which are defined in milliseconds - if (options.delay) { - options.delay = options.delay * 1000; - } - - options.duration = options.time * 1000; - delete options.time; - - if (options.transition) { - //map Tweener easing equations to Clutter animation modes - options.mode = { - 'easeInCubic': Clutter.AnimationMode.EASE_IN_CUBIC, - 'easeInOutCubic': Clutter.AnimationMode.EASE_IN_OUT_CUBIC, - 'easeInOutQuad': Clutter.AnimationMode.EASE_IN_OUT_QUAD, - 'easeOutQuad': Clutter.AnimationMode.EASE_OUT_QUAD - }[options.transition] || Clutter.AnimationMode.LINEAR; - - delete options.transition; - } - - let params = [options]; - - if ('value' in options && actor instanceof St.Adjustment) { - params.unshift(options.value); - delete options.value; - } - - actor.ease.apply(actor, params); -} - -export const isAnimating = function(actor, prop) { - return !!actor.get_transition(prop); -} - -export const stopAnimations = function(actor) { - actor.remove_all_transitions(); -} - -export const getIndicators = function(delegate) { - if (delegate instanceof St.BoxLayout) { - return delegate; - } - - return delegate.indicators; -} - -export const getPoint = function(coords) { - return new Graphene.Point(coords); -} - -export const notify = function(text, iconName, action, isTransient) { - let source = new MessageTray.SystemNotificationSource(); - let notification = new MessageTray.Notification(source, 'Dash to Panel', text); - let notifyFunc = source.showNotification || source.notify; - - if (iconName) { - source.createIcon = function() { - return new St.Icon({ icon_name: iconName }); - }; - } - - if (action) { - if (!(action instanceof Array)) { - action = [action]; - } - - action.forEach(a => notification.addAction(a.text, a.func)); - } - - Main.messageTray.add(source); - - notification.setTransient(isTransient); - notifyFunc.call(source, notification); -}; - -/* - * This is a copy of the same function in utils.js, but also adjust horizontal scrolling - * and perform few further cheks on the current value to avoid changing the values when - * it would be clamp to the current one in any case. - * Return the amount of shift applied -*/ -export const ensureActorVisibleInScrollView = function(scrollView, actor, fadeSize, onComplete) { - let vadjustment = scrollView.vscroll.adjustment; - let hadjustment = scrollView.hscroll.adjustment; - let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] = vadjustment.get_values(); - let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] = hadjustment.get_values(); - - let [hvalue0, vvalue0] = [hvalue, vvalue]; - - let voffset = fadeSize; - let hoffset = fadeSize; - - let box = actor.get_allocation_box(); - let y1 = box.y1, y2 = box.y2, x1 = box.x1, x2 = box.x2; - - let parent = actor.get_parent(); - while (parent != scrollView) { - if (!parent) - throw new Error("actor not in scroll view"); - - let box = parent.get_allocation_box(); - y1 += box.y1; - y2 += box.y1; - x1 += box.x1; - x2 += box.x1; - parent = parent.get_parent(); - } - - if (y1 < vvalue + voffset) - vvalue = Math.max(0, y1 - voffset); - else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset) - vvalue = Math.min(vupper -vpageSize, y2 + voffset - vpageSize); - - if (x1 < hvalue + hoffset) - hvalue = Math.max(0, x1 - hoffset); - else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset) - hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize); - - let tweenOpts = { - time: SCROLL_TIME, - onComplete: onComplete || (() => {}), - transition: 'easeOutQuad' - }; - - if (vvalue !== vvalue0) { - animate(vadjustment, mergeObjects(tweenOpts, { value: vvalue })); - } - - if (hvalue !== hvalue0) { - animate(hadjustment, mergeObjects(tweenOpts, { value: hvalue })); - } - - return [hvalue- hvalue0, vvalue - vvalue0]; -} - -/** - * ColorUtils is adapted from https://github.com/micheleg/dash-to-dock - */ -export const ColorUtils = { - colorLuminance(r, g, b, dlum) { - // Darken or brighten color by a fraction dlum - // Each rgb value is modified by the same fraction. - // Return "#rrggbb" strin - - let rgbString = '#'; - - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r*(1+dlum), 0), 255)), 2); - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g*(1+dlum), 0), 255)), 2); - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b*(1+dlum), 0), 255)), 2); - - return rgbString; - }, - - _decimalToHex(d, padding) { - // Convert decimal to an hexadecimal string adding the desired padding - - let hex = d.toString(16); - while (hex.length < padding) - hex = '0'+ hex; - return hex; - }, - - HSVtoRGB(h, s, v) { - // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]). - // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV - // here with h = [0,1] instead of [0, 360] - // Accept either (h,s,v) independently or {h:h, s:s, v:v} object. - // Return {r:r, g:g, b:b} object. - - if (arguments.length === 1) { - s = h.s; - v = h.v; - h = h.h; - } - - let r,g,b; - let c = v*s; - let h1 = h*6; - let x = c*(1 - Math.abs(h1 % 2 - 1)); - let m = v - c; - - if (h1 <=1) - r = c + m, g = x + m, b = m; - else if (h1 <=2) - r = x + m, g = c + m, b = m; - else if (h1 <=3) - r = m, g = c + m, b = x + m; - else if (h1 <=4) - r = m, g = x + m, b = c + m; - else if (h1 <=5) - r = x + m, g = m, b = c + m; - else - r = c + m, g = m, b = x + m; - - return { - r: Math.round(r * 255), - g: Math.round(g * 255), - b: Math.round(b * 255) - }; - }, - - RGBtoHSV(r, g, b) { - // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]). - // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV - // here with h = [0,1] instead of [0, 360] - // Accept either (r,g,b) independently or {r:r, g:g, b:b} object. - // Return {h:h, s:s, v:v} object. - - if (arguments.length === 1) { - r = r.r; - g = r.g; - b = r.b; - } - - let h,s,v; - - let M = Math.max(r, g, b); - let m = Math.min(r, g, b); - let c = M - m; - - if (c == 0) - h = 0; - else if (M == r) - h = ((g-b)/c) % 6; - else if (M == g) - h = (b-r)/c + 2; - else - h = (r-g)/c + 4; - - h = h/6; - v = M/255; - if (M !== 0) - s = c/M; - else - s = 0; - - return {h: h, s: s, v: v}; - } -}; - -/** - * DominantColorExtractor is adapted from https://github.com/micheleg/dash-to-dock - */ -let themeLoader = null; -let iconCacheMap = new Map(); -const MAX_CACHED_ITEMS = 1000; -const BATCH_SIZE_TO_DELETE = 50; -const DOMINANT_COLOR_ICON_SIZE = 64; - -export const DominantColorExtractor = class { - - constructor(app){ - this._app = app; - } - - /** - * Try to get the pixel buffer for the current icon, if not fail gracefully - */ - _getIconPixBuf() { - let iconTexture = this._app.create_icon_texture(16); - - if (themeLoader === null) { - themeLoader = new St.IconTheme(); - } - - // Unable to load the icon texture, use fallback - if (iconTexture instanceof St.Icon === false) { - return null; - } - - iconTexture = iconTexture.get_gicon(); - - // Unable to load the icon texture, use fallback - if (iconTexture === null) { - return null; - } - - if (iconTexture instanceof Gio.FileIcon) { - // Use GdkPixBuf to load the pixel buffer from the provided file path - return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path()); - } - - // Get the pixel buffer from the icon theme - if (iconTexture instanceof Gio.ThemedIcon) { - let icon_info = themeLoader.lookup_icon(iconTexture.get_names()[0], - DOMINANT_COLOR_ICON_SIZE, 0); - - if (icon_info !== null) { - return icon_info.load_icon(); - } - } - - return null; - } - - /** - * The backlight color choosing algorithm was mostly ported to javascript from the - * Unity7 C++ source of Canonicals: - * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp - * so it more or less works the same way. - */ - _getColorPalette() { - if (iconCacheMap.get(this._app.get_id())) { - // We already know the answer - return iconCacheMap.get(this._app.get_id()); - } - - let pixBuf = this._getIconPixBuf(); - if (pixBuf == null) - return null; - - let pixels = pixBuf.get_pixels(), - offset = 0; - - let total = 0, - rTotal = 0, - gTotal = 0, - bTotal = 0; - - let resample_y = 1, - resample_x = 1; - - // Resampling of large icons - // We resample icons larger than twice the desired size, as the resampling - // to a size s - // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE, - // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally - // a multiple of it. - let width = pixBuf.get_width(); - let height = pixBuf.get_height(); - - // Resample - if (height >= 2* DOMINANT_COLOR_ICON_SIZE) - resample_y = Math.floor(height/DOMINANT_COLOR_ICON_SIZE); - - if (width >= 2* DOMINANT_COLOR_ICON_SIZE) - resample_x = Math.floor(width/DOMINANT_COLOR_ICON_SIZE); - - if (resample_x !==1 || resample_y !== 1) - pixels = this._resamplePixels(pixels, resample_x, resample_y); - - // computing the limit outside the for (where it would be repeated at each iteration) - // for performance reasons - let limit = pixels.length; - for (let offset = 0; offset < limit; offset+=4) { - let r = pixels[offset], - g = pixels[offset + 1], - b = pixels[offset + 2], - a = pixels[offset + 3]; - - let saturation = (Math.max(r,g, b) - Math.min(r,g, b)); - let relevance = 0.1 * 255 * 255 + 0.9 * a * saturation; - - rTotal += r * relevance; - gTotal += g * relevance; - bTotal += b * relevance; - - total += relevance; - } - - total = total * 255; - - let r = rTotal / total, - g = gTotal / total, - b = bTotal / total; - - let hsv = ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255); - - if (hsv.s > 0.15) - hsv.s = 0.65; - hsv.v = 0.90; - - let rgb = ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v); - - // Cache the result. - let backgroundColor = { - lighter: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0.2), - original: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0), - darker: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, -0.5) - }; - - if (iconCacheMap.size >= MAX_CACHED_ITEMS) { - //delete oldest cached values (which are in order of insertions) - let ctr=0; - for (let key of iconCacheMap.keys()) { - if (++ctr > BATCH_SIZE_TO_DELETE) - break; - iconCacheMap.delete(key); - } - } - - iconCacheMap.set(this._app.get_id(), backgroundColor); - - return backgroundColor; - } - - /** - * Downsample large icons before scanning for the backlight color to - * improve performance. - * - * @param pixBuf - * @param pixels - * @param resampleX - * @param resampleY - * - * @return []; - */ - _resamplePixels(pixels, resampleX, resampleY) { - let resampledPixels = []; - // computing the limit outside the for (where it would be repeated at each iteration) - // for performance reasons - let limit = pixels.length / (resampleX * resampleY) / 4; - for (let i = 0; i < limit; i++) { - let pixel = i * resampleX * resampleY; - - resampledPixels.push(pixels[pixel * 4]); - resampledPixels.push(pixels[pixel * 4 + 1]); - resampledPixels.push(pixels[pixel * 4 + 2]); - resampledPixels.push(pixels[pixel * 4 + 3]); - } - - return resampledPixels; - } - -}; - -export const drawRoundedLine = function(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) { - if (height > width) { - y += Math.floor((height - width) / 2.0); - height = width; - } - - height = 2.0 * Math.floor(height / 2.0); - - const leftRadius = isRoundLeft ? height / 2.0 : 0.0; - const rightRadius = isRoundRight ? height / 2.0 : 0.0; - - cr.moveTo(x + width - rightRadius, y); - cr.lineTo(x + leftRadius, y); - if (isRoundLeft) - cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI/2, Math.PI/2); - else - cr.lineTo(x, y + height); - cr.lineTo(x + width - rightRadius, y + height); - if (isRoundRight) - cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI/2, -Math.PI/2); - else - cr.lineTo(x + width, y); - cr.closePath(); - - if (fill != null) { - cr.setSource(fill); - cr.fillPreserve(); - } - if (stroke != null) - cr.setSource(stroke); - cr.stroke(); -} diff --git a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/windowPreview.js b/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/windowPreview.js deleted file mode 100644 index d9c1d67..0000000 --- a/.local/share/gnome-shell/extensions/dash-to-panel@jderose9.github.com/windowPreview.js +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * This file is part of the Dash-To-Panel extension for Gnome 3 - * - * 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 . - */ - -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import Graphene from 'gi://Graphene'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Meta from 'gi://Meta'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import St from 'gi://St'; - -import * as Taskbar from './taskbar.js'; -import * as Utils from './utils.js'; -import {SETTINGS, DESKTOPSETTINGS} from './extension.js'; -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -//timeout intervals -const ENSURE_VISIBLE_MS = 200; - -//timeout names -const T1 = 'openMenuTimeout'; -const T2 = 'closeMenuTimeout'; -const T3 = 'peekTimeout'; -const T4 = 'ensureVisibleTimeout'; - -const MAX_TRANSLATION = 40; -const HEADER_HEIGHT = 38; -const MAX_CLOSE_BUTTON_SIZE = 30; -const MIN_DIMENSION = 100; -const FOCUSED_COLOR_OFFSET = 24; -const HEADER_COLOR_OFFSET = -12; -const FADE_SIZE = 36; -const PEEK_INDEX_PROP = '_dtpPeekInitialIndex'; - -let headerHeight = 0; -let alphaBg = 0; -let isLeftButtons = false; -let isTopHeader = true; -let isManualStyling = false; -let scaleFactor = 1; -let animationTime = 0; -let aspectRatio = {}; - -export const PreviewMenu = GObject.registerClass({ - Signals: { 'open-state-changed': {} } -}, class PreviewMenu extends St.Widget { - - _init(panel) { - super._init({ layout_manager: new Clutter.BinLayout() }); - - let geom = panel.geom; - this.panel = panel; - this.currentAppIcon = null; - this._focusedPreview = null; - this._peekedWindow = null; - this.allowCloseWindow = true; - this.peekInitialWorkspaceIndex = -1; - this.opened = false; - this.isVertical = geom.position == St.Side.LEFT || geom.position == St.Side.RIGHT; - this._translationProp = 'translation_' + (this.isVertical ? 'x' : 'y'); - this._translationDirection = (geom.position == St.Side.TOP || geom.position == St.Side.LEFT ? -1 : 1); - this._translationOffset = Math.min(panel.dtpSize, MAX_TRANSLATION) * this._translationDirection; - - this.menu = new St.Widget({ - name: 'preview-menu', - layout_manager: new Clutter.BinLayout(), - reactive: true, - track_hover: true, - x_expand: true, - y_expand: true, - x_align: Clutter.ActorAlign[geom.position != St.Side.RIGHT ? 'START' : 'END'], - y_align: Clutter.ActorAlign[geom.position != St.Side.BOTTOM ? 'START' : 'END'] - }); - this._box = new St.BoxLayout({ vertical: this.isVertical }); - this._scrollView = new St.ScrollView({ - name: 'dashtopanelPreviewScrollview', - hscrollbar_policy: St.PolicyType.NEVER, - vscrollbar_policy: St.PolicyType.NEVER, - enable_mouse_scrolling: true, - y_expand: !this.isVertical - }); - - this._scrollView.add_actor(this._box); - this.menu.add_child(this._scrollView); - this.add_child(this.menu); - } - - enable() { - this._timeoutsHandler = new Utils.TimeoutsHandler(); - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - Main.layoutManager.addChrome(this, { affectsInputRegion: false }); - Main.layoutManager.trackChrome(this.menu, { affectsInputRegion: true }); - - this._resetHiddenState(); - this._refreshGlobals(); - this._updateClip(); - this.menu.set_position(1, 1); - - this._signalsHandler.add( - [ - this.menu, - 'notify::hover', - () => this._onHoverChanged() - ], - [ - this._scrollView, - 'scroll-event', - this._onScrollEvent.bind(this) - ], - [ - this.panel.panelBox, - 'style-changed', - () => this._updateClip() - ], - [ - Utils.DisplayWrapper.getScreen(), - 'in-fullscreen-changed', - () => { - if (global.display.focus_window && global.display.focus_window.is_fullscreen()) { - this.close(true); - } - } - ], - [ - SETTINGS, - [ - 'changed::panel-sizes', - 'changed::window-preview-size', - 'changed::window-preview-padding', - 'changed::window-preview-show-title' - ], - () => { - this._refreshGlobals(); - this._updateClip(); - } - ] - ); - } - - disable() { - this._timeoutsHandler.destroy(); - this._signalsHandler.destroy(); - - this.close(true); - - Main.layoutManager.untrackChrome(this.menu); - Main.layoutManager.removeChrome(this); - } - - requestOpen(appIcon) { - let timeout = SETTINGS.get_int('show-window-previews-timeout'); - - if (this.opened) { - timeout = Math.min(100, timeout); - } - - this._endOpenCloseTimeouts(); - this._timeoutsHandler.add([T1, timeout, () => this.open(appIcon)]); - } - - requestClose() { - this._endOpenCloseTimeouts(); - this._addCloseTimeout(); - } - - open(appIcon, preventCloseWindow) { - if (this.currentAppIcon != appIcon) { - this.currentAppIcon = appIcon; - this.allowCloseWindow = !preventCloseWindow; - - if (!this.opened) { - this._refreshGlobals(); - - this.set_height(this.clipHeight); - this.menu.show(); - - setStyle(this.menu, 'background: ' + Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, alphaBg)); - } - - this._mergeWindows(appIcon); - this._updatePosition(); - this._animateOpenOrClose(true); - - this._setReactive(true); - this._setOpenedState(true); - } - } - - close(immediate) { - this._endOpenCloseTimeouts(); - this._removeFocus(); - this._endPeek(); - - if (immediate) { - Utils.stopAnimations(this.menu); - this._resetHiddenState(); - } else { - this._animateOpenOrClose(false, () => this._resetHiddenState()); - } - - this._setReactive(false); - this.currentAppIcon = null; - } - - update(appIcon, windows) { - if (this.currentAppIcon == appIcon) { - if (windows && !windows.length) { - this.close(); - } else { - this._addAndRemoveWindows(windows); - this._updatePosition(); - } - } - } - - updatePosition() { - this._updatePosition(); - } - - focusNext() { - let previews = this._box.get_children(); - let currentIndex = this._focusedPreview ? previews.indexOf(this._focusedPreview) : -1; - let nextIndex = currentIndex + 1; - - nextIndex = previews[nextIndex] ? nextIndex : 0; - - if (previews[nextIndex]) { - this._removeFocus(); - previews[nextIndex].setFocus(true); - this._focusedPreview = previews[nextIndex]; - } - - return nextIndex; - } - - activateFocused() { - if (this.opened && this._focusedPreview) { - this._focusedPreview.activate(); - } - } - - requestPeek(window) { - this._timeoutsHandler.remove(T3); - - if (SETTINGS.get_boolean('peek-mode')) { - if (this.peekInitialWorkspaceIndex < 0) { - this._timeoutsHandler.add([T3, SETTINGS.get_int('enter-peek-mode-timeout'), () => this._peek(window)]); - } else { - this._peek(window); - } - } - } - - endPeekHere() { - this._endPeek(true); - } - - ensureVisible(preview) { - let [ , upper, pageSize] = this._getScrollAdjustmentValues(); - - if (upper > pageSize) { - this._timeoutsHandler.add([ - T4, - ENSURE_VISIBLE_MS, - () => Utils.ensureActorVisibleInScrollView(this._scrollView, preview, MIN_DIMENSION, () => this._updateScrollFade()) - ]); - } - } - - getCurrentAppIcon() { - return this.currentAppIcon; - } - - _setReactive(reactive) { - this._box.get_children().forEach(c => c.reactive = reactive); - this.menu.reactive = reactive; - } - - _setOpenedState(opened) { - this.opened = opened; - this.emit('open-state-changed'); - } - - _resetHiddenState() { - this.menu.hide(); - this.set_height(0); - this._setOpenedState(false); - this.menu.opacity = 0; - this.menu[this._translationProp] = this._translationOffset; - this._box.get_children().forEach(c => c.destroy()); - } - - _removeFocus() { - if (this._focusedPreview) { - this._focusedPreview.setFocus(false); - this._focusedPreview = null; - } - } - - _mergeWindows(appIcon, windows) { - windows = windows || (appIcon.window ? [appIcon.window] : appIcon.getAppIconInterestingWindows()); - windows.sort(Taskbar.sortWindowsCompareFunction); - - let currentPreviews = this._box.get_children(); - let l = Math.max(windows.length, currentPreviews.length); - - for (let i = 0; i < l; ++i) { - if (currentPreviews[i] && windows[i]) { - currentPreviews[i].assignWindow(windows[i], this.opened); - } else if (!currentPreviews[i]) { - this._addNewPreview(windows[i]); - } else if (!windows[i]) { - currentPreviews[i][!this.opened ? 'destroy' : 'animateOut'](); - } - } - } - - _addAndRemoveWindows(windows) { - let currentPreviews = this._box.get_children(); - - windows.sort(Taskbar.sortWindowsCompareFunction); - - for (let i = 0, l = windows.length; i < l; ++i) { - let currentIndex = Utils.findIndex(currentPreviews, c => c.window == windows[i]); - - if (currentIndex < 0) { - this._addNewPreview(windows[i]); - } else { - currentPreviews[currentIndex].assignWindow(windows[i]); - currentPreviews.splice(currentIndex, 1); - - if (this._peekedWindow && this._peekedWindow == windows[i]) { - this.requestPeek(windows[i]); - } - } - } - - currentPreviews.forEach(c => c.animateOut()); - } - - _addNewPreview(window) { - let preview = new Preview(this); - - this._box.add_child(preview); - preview.adjustOnStage(); - preview.assignWindow(window, this.opened); - } - - _addCloseTimeout() { - this._timeoutsHandler.add([T2, SETTINGS.get_int('leave-timeout'), () => this.close()]); - } - - _onHoverChanged() { - this._endOpenCloseTimeouts(); - - if (this.currentAppIcon && !this.menu.hover) { - this._addCloseTimeout(); - this._endPeek(); - } - } - - _onScrollEvent(actor, event) { - if (!event.is_pointer_emulated()) { - let vOrh = this.isVertical ? 'v' : 'h'; - let adjustment = this._scrollView['get_' + vOrh + 'scroll_bar']().get_adjustment(); - let increment = adjustment.step_increment; - let delta = increment; - - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - delta = -increment; - break; - case Clutter.ScrollDirection.SMOOTH: - let [dx, dy] = event.get_scroll_delta(); - delta = dy * increment; - delta += dx * increment; - break; - } - - adjustment.set_value(adjustment.get_value() + delta); - this._updateScrollFade(); - } - - return Clutter.EVENT_STOP; - } - - _endOpenCloseTimeouts() { - this._timeoutsHandler.remove(T1); - this._timeoutsHandler.remove(T2); - this._timeoutsHandler.remove(T4); - } - - _refreshGlobals() { - isLeftButtons = Meta.prefs_get_button_layout().left_buttons.indexOf(Meta.ButtonFunction.CLOSE) >= 0; - isTopHeader = SETTINGS.get_string('window-preview-title-position') == 'TOP'; - isManualStyling = SETTINGS.get_boolean('window-preview-manual-styling'); - scaleFactor = Utils.getScaleFactor(); - headerHeight = SETTINGS.get_boolean('window-preview-show-title') ? HEADER_HEIGHT * scaleFactor : 0; - animationTime = SETTINGS.get_int('window-preview-animation-time') * .001; - aspectRatio.x = { - size: SETTINGS.get_int('window-preview-aspect-ratio-x'), - fixed: SETTINGS.get_boolean('window-preview-fixed-x') - }; - aspectRatio.y = { - size: SETTINGS.get_int('window-preview-aspect-ratio-y'), - fixed: SETTINGS.get_boolean('window-preview-fixed-y') - }; - - alphaBg = SETTINGS.get_boolean('preview-use-custom-opacity') ? - SETTINGS.get_int('preview-custom-opacity') * .01 : - this.panel.dynamicTransparency.alpha; - } - - _updateClip() { - let x, y, w; - let geom = this.panel.getGeometry(); - let panelBoxTheme = this.panel.panelBox.get_theme_node(); - let previewSize = (SETTINGS.get_int('window-preview-size') + - SETTINGS.get_int('window-preview-padding') * 2) * scaleFactor; - - if (this.isVertical) { - w = previewSize; - this.clipHeight = this.panel.monitor.height; - y = this.panel.monitor.y; - } else { - w = this.panel.monitor.width; - this.clipHeight = (previewSize + headerHeight); - x = this.panel.monitor.x; - } - - if (geom.position == St.Side.LEFT) { - x = this.panel.monitor.x + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.LEFT); - } else if (geom.position == St.Side.RIGHT) { - x = this.panel.monitor.x + this.panel.monitor.width - (this.panel.dtpSize + previewSize) - panelBoxTheme.get_padding(St.Side.RIGHT); - } else if (geom.position == St.Side.TOP) { - y = this.panel.monitor.y + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.TOP); - } else { //St.Side.BOTTOM - y = this.panel.monitor.y + this.panel.monitor.height - (this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.BOTTOM) + previewSize + headerHeight); - } - - Utils.setClip(this, x, y, w, this.clipHeight); - } - - _updatePosition() { - let sourceNode = this.currentAppIcon.get_theme_node(); - let sourceContentBox = sourceNode.get_content_box(this.currentAppIcon.get_allocation_box()); - let sourceAllocation = Utils.getTransformedAllocation(this.currentAppIcon); - let [previewsWidth, previewsHeight] = this._getPreviewsSize(); - let appIconMargin = SETTINGS.get_int('appicon-margin') / scaleFactor; - let x = 0, y = 0; - - previewsWidth = Math.min(previewsWidth, this.panel.monitor.width); - previewsHeight = Math.min(previewsHeight, this.panel.monitor.height); - this._updateScrollFade(previewsWidth < this.panel.monitor.width && previewsHeight < this.panel.monitor.height); - - if (this.isVertical) { - y = sourceAllocation.y1 + appIconMargin - this.panel.monitor.y + (sourceContentBox.y2 - sourceContentBox.y1 - previewsHeight) * .5; - y = Math.max(y, 0); - y = Math.min(y, this.panel.monitor.height - previewsHeight); - } else { - x = sourceAllocation.x1 + appIconMargin - this.panel.monitor.x + (sourceContentBox.x2 - sourceContentBox.x1 - previewsWidth) * .5; - x = Math.max(x, 0); - x = Math.min(x, this.panel.monitor.width - previewsWidth); - } - - if (!this.opened) { - this.menu.set_position(x, y); - this.menu.set_size(previewsWidth, previewsHeight); - } else { - Utils.animate(this.menu, getTweenOpts({ x: x, y: y, width: previewsWidth, height: previewsHeight })); - } - } - - _updateScrollFade(remove) { - let [value, upper, pageSize] = this._getScrollAdjustmentValues(); - let needsFade = Math.round(upper) > Math.round(pageSize); - let fadeWidgets = this.menu.get_children().filter(c => c != this._scrollView); - - if (!remove && needsFade) { - if (!fadeWidgets.length) { - fadeWidgets.push(this._getFadeWidget()); - fadeWidgets.push(this._getFadeWidget(true)); - - this.menu.add_child(fadeWidgets[0]); - this.menu.add_child(fadeWidgets[1]); - } - - fadeWidgets[0].visible = value > 0; - fadeWidgets[1].visible = value + pageSize < upper; - } else if (remove || (!needsFade && fadeWidgets.length)) { - fadeWidgets.forEach(fw => fw.destroy()); - } - } - - _getScrollAdjustmentValues() { - let [value , , upper, , , pageSize] = this._scrollView[(this.isVertical ? 'v' : 'h') + 'scroll'].adjustment.get_values(); - - return [value, upper, pageSize]; - } - - _getFadeWidget(end) { - let x = 0, y = 0; - let startBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, Math.min(alphaBg + .1, 1)); - let endBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, 0) - let fadeStyle = 'background-gradient-start:' + startBg + - 'background-gradient-end:' + endBg + - 'background-gradient-direction:' + this.panel.getOrientation(); - - if (this.isVertical) { - y = end ? this.panel.monitor.height - FADE_SIZE : 0; - } else { - x = end ? this.panel.monitor.width - FADE_SIZE : 0; - } - - let fadeWidget = new St.Widget({ - reactive: false, - pivot_point: new Graphene.Point({ x: .5, y: .5 }), - rotation_angle_z: end ? 180 : 0, - style: fadeStyle, - x: x, y: y, - width: this.isVertical ? this.width : FADE_SIZE, - height: this.isVertical ? FADE_SIZE : this.height - }); - - return fadeWidget; - } - - _getPreviewsSize() { - let previewsWidth = 0; - let previewsHeight = 0; - - this._box.get_children().forEach(c => { - if (!c.animatingOut) { - let [width, height] = c.getSize(); - - if (this.isVertical) { - previewsWidth = Math.max(width, previewsWidth); - previewsHeight += height; - } else { - previewsWidth += width; - previewsHeight = Math.max(height, previewsHeight); - } - } - }); - - return [previewsWidth, previewsHeight]; - } - - _animateOpenOrClose(show, onComplete) { - let isTranslationAnimation = this.menu[this._translationProp] != 0; - let tweenOpts = { - opacity: show ? 255 : 0, - transition: show ? 'easeInOutQuad' : 'easeInCubic', - onComplete: () => { - if (isTranslationAnimation) { - Main.layoutManager._queueUpdateRegions(); - } - - (onComplete || (() => {}))(); - } - }; - - tweenOpts[this._translationProp] = show ? this._translationDirection : this._translationOffset; - - Utils.animate(this.menu, getTweenOpts(tweenOpts)); - } - - _peek(window) { - let currentWorkspace = Utils.getCurrentWorkspace(); - let windowWorkspace = window.get_workspace(); - let focusWindow = () => this._focusMetaWindow(SETTINGS.get_int('peek-mode-opacity'), window); - - this._restorePeekedWindowStack(); - - if (this._peekedWindow && windowWorkspace != currentWorkspace) { - currentWorkspace.list_windows().forEach(mw => this.animateWindowOpacity(mw, null, 255)) - } - - this._peekedWindow = window; - - if (currentWorkspace != windowWorkspace) { - this._switchToWorkspaceImmediate(windowWorkspace.index()); - this._timeoutsHandler.add([T3, 100, focusWindow]); - } else { - focusWindow(); - } - - if (this.peekInitialWorkspaceIndex < 0) { - this.peekInitialWorkspaceIndex = currentWorkspace.index(); - } - } - - _endPeek(stayHere) { - this._timeoutsHandler.remove(T3); - - if (this._peekedWindow) { - let immediate = !stayHere && this.peekInitialWorkspaceIndex != Utils.getCurrentWorkspace().index(); - - this._restorePeekedWindowStack(); - this._focusMetaWindow(255, this._peekedWindow, immediate, true); - this._peekedWindow = null; - - if (!stayHere) { - this._switchToWorkspaceImmediate(this.peekInitialWorkspaceIndex); - } - - this.peekInitialWorkspaceIndex = -1; - } - } - - _switchToWorkspaceImmediate(workspaceIndex) { - let workspace = Utils.getWorkspaceByIndex(workspaceIndex); - let shouldAnimate = Main.wm._shouldAnimate; - - if (!workspace || (!workspace.list_windows().length && - workspaceIndex < Utils.getWorkspaceCount() - 1)) { - workspace = Utils.getCurrentWorkspace(); - } - - Main.wm._shouldAnimate = () => false; - workspace.activate(global.display.get_current_time_roundtrip()); - Main.wm._shouldAnimate = shouldAnimate; - } - - _focusMetaWindow(dimOpacity, window, immediate, ignoreFocus) { - window.get_workspace().list_windows().forEach(mw => { - let wa = mw.get_compositor_private(); - let isFocused = !ignoreFocus && mw == window; - - if (wa) { - if (isFocused) { - mw[PEEK_INDEX_PROP] = wa.get_parent().get_children().indexOf(wa); - wa.get_parent().set_child_above_sibling(wa, null); - } - - if (isFocused && mw.minimized) { - wa.show(); - } - - this.animateWindowOpacity(mw, wa, isFocused ? 255 : dimOpacity, immediate) - } - }); - } - - animateWindowOpacity(metaWindow, windowActor, opacity, immediate) { - windowActor = windowActor || metaWindow.get_compositor_private(); - - if (windowActor && !metaWindow.minimized) { - let tweenOpts = getTweenOpts({ opacity }); - - if (immediate && !metaWindow.is_on_all_workspaces()) { - tweenOpts.time = 0; - } - - Utils.animateWindowOpacity(windowActor, tweenOpts); - } - } - - _restorePeekedWindowStack() { - let windowActor = this._peekedWindow ? this._peekedWindow.get_compositor_private() : null; - - if (windowActor) { - if (this._peekedWindow.hasOwnProperty(PEEK_INDEX_PROP)) { - windowActor.get_parent().set_child_at_index(windowActor, this._peekedWindow[PEEK_INDEX_PROP]); - delete this._peekedWindow[PEEK_INDEX_PROP]; - } - - if (this._peekedWindow.minimized) { - windowActor.hide(); - } - } - } -}); - -export const Preview = GObject.registerClass({ -}, class Preview extends St.Widget { - - _init(previewMenu) { - super._init({ - style_class: 'preview-container', - reactive: true, - track_hover: true, - layout_manager: new Clutter.BinLayout() - }); - - this.window = null; - this._waitWindowId = 0; - this._needsCloseButton = true; - this.cloneWidth = this.cloneHeight = 0; - this._previewMenu = previewMenu; - this._padding = SETTINGS.get_int('window-preview-padding') * scaleFactor; - this._previewDimensions = this._getPreviewDimensions(); - this.animatingOut = false; - - let box = new St.Widget({ layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL }), y_expand: true }); - let [previewBinWidth, previewBinHeight] = this._getBinSize(); - let closeButton = new St.Button({ style_class: 'window-close', accessible_name: 'Close window' }); - - closeButton.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' })); - - this._closeButtonBin = new St.Widget({ - style_class: 'preview-close-btn-container', - layout_manager: new Clutter.BinLayout(), - opacity: 0, - x_expand: true, y_expand: true, - x_align: Clutter.ActorAlign[isLeftButtons ? 'START' : 'END'], - y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'] - }); - - this._closeButtonBin.add_child(closeButton); - - this._previewBin = new St.Widget({ - layout_manager: new Clutter.BinLayout(), - x_expand: true, y_expand: true, - style: 'padding: ' + this._padding / scaleFactor + 'px;' - }); - - this._previewBin.set_size(previewBinWidth, previewBinHeight); - - box.add_child(this._previewBin); - - if (headerHeight) { - let headerBox = new St.Widget({ - style_class: 'preview-header-box', - layout_manager: new Clutter.BoxLayout(), - x_expand: true, - y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'] - }); - - setStyle(headerBox, this._getBackgroundColor(HEADER_COLOR_OFFSET, 1)); - this._workspaceIndicator = new St.Label({ y_align: Clutter.ActorAlign.CENTER }); - this._windowTitle = new St.Label({ y_align: Clutter.ActorAlign.CENTER, x_expand: true }); - - this._iconBin = new St.Widget({ layout_manager: new Clutter.BinLayout() }); - this._iconBin.set_size(headerHeight, headerHeight); - - headerBox.add_child(this._iconBin); - headerBox.insert_child_at_index(this._workspaceIndicator, isLeftButtons ? 0 : 1); - headerBox.insert_child_at_index(this._windowTitle, isLeftButtons ? 1 : 2); - - box.insert_child_at_index(headerBox, isTopHeader ? 0 : 1); - } - - this.add_child(box); - this.add_child(this._closeButtonBin); - - closeButton.connect('clicked', () => this._onCloseBtnClick()); - this.connect('notify::hover', () => this._onHoverChanged()); - this.connect('button-release-event', (actor, e) => this._onButtonReleaseEvent(e)); - this.connect('destroy', () => this._onDestroy()); - } - - adjustOnStage() { - let closeButton = this._closeButtonBin.get_first_child(); - let closeButtonHeight = closeButton.height; - let maxCloseButtonSize = MAX_CLOSE_BUTTON_SIZE * scaleFactor; - let closeButtonBorderRadius = ''; - - if (closeButtonHeight > maxCloseButtonSize) { - closeButtonHeight = maxCloseButtonSize; - closeButton.set_size(closeButtonHeight, closeButtonHeight); - } - - if (!headerHeight) { - closeButtonBorderRadius = 'border-radius: '; - - if (isTopHeader) { - closeButtonBorderRadius += (isLeftButtons ? '0 0 4px 0;' : '0 0 0 4px;'); - } else { - closeButtonBorderRadius += (isLeftButtons ? '0 4px 0 0;' : '4px 0 0 0;'); - } - } - - setStyle( - this._closeButtonBin, - 'padding: ' + (headerHeight ? Math.round((headerHeight - closeButtonHeight) * .5 / scaleFactor) : 4) + 'px;' + - this._getBackgroundColor(HEADER_COLOR_OFFSET, headerHeight ? 1 : .6) + - closeButtonBorderRadius - ); - } - - assignWindow(window, animateSize) { - if (this.window != window) { - let _assignWindowClone = () => { - if (window.get_compositor_private()) { - let cloneBin = this._getWindowCloneBin(window); - - this._resizeClone(cloneBin, window); - this._addClone(cloneBin, animateSize); - this._previewMenu.updatePosition(); - } else if (!this._waitWindowId) { - this._waitWindowId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - this._waitWindowId = 0; - - if (this._previewMenu.opened) { - _assignWindowClone(); - } - - return GLib.SOURCE_REMOVE; - }); - } - }; - - _assignWindowClone(); - } - - this._cancelAnimateOut(); - this._removeWindowSignals(); - this.window = window; - this._needsCloseButton = this._previewMenu.allowCloseWindow && window.can_close() && !Utils.checkIfWindowHasTransient(window); - this._updateHeader(); - } - - animateOut() { - if (!this.animatingOut) { - let tweenOpts = getTweenOpts({ opacity: 0, width: 0, height: 0, onComplete: () => this.destroy() }); - - this.animatingOut = true; - - Utils.stopAnimations(this); - Utils.animate(this, tweenOpts); - } - } - - getSize() { - let [binWidth, binHeight] = this._getBinSize(); - - binWidth = Math.max(binWidth, this.cloneWidth + this._padding * 2); - binHeight = Math.max(binHeight, this.cloneHeight + this._padding * 2) + headerHeight; - - return [binWidth, binHeight]; - } - - setFocus(focused) { - this._hideOrShowCloseButton(!focused); - setStyle(this, this._getBackgroundColor(FOCUSED_COLOR_OFFSET, focused ? '-' : 0)); - - if (focused) { - this._previewMenu.ensureVisible(this); - this._previewMenu.requestPeek(this.window); - } - } - - activate() { - this._previewMenu.endPeekHere(); - this._previewMenu.close(); - Main.activateWindow(this.window); - } - - _onDestroy() { - if (this._waitWindowId) { - GLib.source_remove(this._waitWindowId); - this._waitWindowId = 0; - } - - this._removeWindowSignals(); - } - - _onHoverChanged() { - this.setFocus(this.hover); - } - - _onCloseBtnClick() { - this._hideOrShowCloseButton(true); - this.reactive = false; - - if (!SETTINGS.get_boolean('group-apps')) { - this._previewMenu.close(); - } else { - this._previewMenu.endPeekHere(); - } - - this.window.delete(global.get_current_time()); - } - - _onButtonReleaseEvent(e) { - switch (e.get_button()) { - case 1: // Left click - this.activate(); - break; - case 2: // Middle click - if (SETTINGS.get_boolean('preview-middle-click-close')) { - this._onCloseBtnClick(); - } - break; - case 3: // Right click - this._showContextMenu(e); - break; - } - - return Clutter.EVENT_STOP; - } - - _cancelAnimateOut() { - if (this.animatingOut) { - this.animatingOut = false; - - Utils.stopAnimations(this); - Utils.animate(this, getTweenOpts({ opacity: 255, width: this.cloneWidth, height: this.cloneHeight })); - } - } - - _showContextMenu(e) { - let coords = e.get_coords(); - let currentWorkspace = this._previewMenu.peekInitialWorkspaceIndex < 0 ? - Utils.getCurrentWorkspace() : - Utils.getWorkspaceByIndex(this._previewMenu.peekInitialWorkspaceIndex); - - Main.wm._showWindowMenu(null, this.window, Meta.WindowMenuType.WM, { - x: coords[0], - y: coords[1], - width: 0, - height: 0 - }); - - let menu = Main.wm._windowMenuManager._manager._menus[0]; - - menu.connect('open-state-changed', () => this._previewMenu.menu.sync_hover()); - this._previewMenu.menu.sync_hover(); - - if (this.window.get_workspace() != currentWorkspace) { - let menuItem = new PopupMenu.PopupMenuItem(_('Move to current Workspace') + ' [' + (currentWorkspace.index() + 1) + ']'); - let menuItems = menu.box.get_children(); - let insertIndex = Utils.findIndex(menuItems, c => c._delegate instanceof PopupMenu.PopupSeparatorMenuItem); - - insertIndex = insertIndex >= 0 ? insertIndex : menuItems.length - 1; - menu.addMenuItem(menuItem, insertIndex); - menuItem.connect('activate', () => this.window.change_workspace(currentWorkspace)); - } - } - - _removeWindowSignals() { - if (this._titleWindowChangeId) { - this.window.disconnect(this._titleWindowChangeId); - this._titleWindowChangeId = 0; - } - } - - _updateHeader() { - if (headerHeight) { - let iconTextureSize = SETTINGS.get_boolean('window-preview-use-custom-icon-size') ? - SETTINGS.get_int('window-preview-custom-icon-size') : - headerHeight / scaleFactor * .6; - let icon = this._previewMenu.getCurrentAppIcon().app.create_icon_texture(iconTextureSize); - let workspaceIndex = ''; - let workspaceStyle = null; - let fontScale = DESKTOPSETTINGS.get_double('text-scaling-factor'); - let commonTitleStyles = 'color: ' + SETTINGS.get_string('window-preview-title-font-color') + ';' + - 'font-size: ' + SETTINGS.get_int('window-preview-title-font-size') * fontScale + 'px;' + - 'font-weight: ' + SETTINGS.get_string('window-preview-title-font-weight') + ';'; - - this._iconBin.destroy_all_children(); - this._iconBin.add_child(icon); - - if (!SETTINGS.get_boolean('isolate-workspaces')) { - workspaceIndex = (this.window.get_workspace().index() + 1).toString(); - workspaceStyle = 'margin: 0 4px 0 ' + (isLeftButtons ? Math.round((headerHeight - icon.width) * .5) + 'px' : '0') + '; padding: 0 4px;' + - 'border: 2px solid ' + this._getRgbaColor(FOCUSED_COLOR_OFFSET, .8) + 'border-radius: 2px;' + commonTitleStyles; - } - - this._workspaceIndicator.text = workspaceIndex; - setStyle(this._workspaceIndicator, workspaceStyle); - - this._titleWindowChangeId = this.window.connect('notify::title', () => this._updateWindowTitle()); - setStyle(this._windowTitle, 'max-width: 0px; padding-right: 4px;' + commonTitleStyles); - this._updateWindowTitle(); - } - } - - _updateWindowTitle() { - this._windowTitle.text = this.window.title; - } - - _hideOrShowCloseButton(hide) { - if (this._needsCloseButton) { - Utils.animate(this._closeButtonBin, getTweenOpts({ opacity: hide ? 0 : 255 })); - } - } - - _getBackgroundColor(offset, alpha) { - return 'background-color: ' + this._getRgbaColor(offset, alpha) + - 'transition-duration:' + this._previewMenu.panel.dynamicTransparency.animationDuration; - } - - _getRgbaColor(offset, alpha) { - alpha = Math.abs(alpha); - - if (isNaN(alpha)) { - alpha = alphaBg; - } - - return Utils.getrgbaColor(this._previewMenu.panel.dynamicTransparency.backgroundColorRgb, alpha, offset); - } - - _addClone(newCloneBin, animateSize) { - let currentClones = this._previewBin.get_children(); - let newCloneOpts = getTweenOpts({ opacity: 255 }); - - this._previewBin.add_child(newCloneBin); - - if (currentClones.length) { - let currentCloneBin = currentClones.pop(); - let currentCloneOpts = getTweenOpts({ opacity: 0, onComplete: () => currentCloneBin.destroy() }); - - if (newCloneBin.width > currentCloneBin.width) { - newCloneOpts.width = newCloneBin.width; - newCloneBin.width = currentCloneBin.width; - } else { - currentCloneOpts.width = newCloneBin.width; - } - - if (newCloneBin.height > currentCloneBin.height) { - newCloneOpts.height = newCloneBin.height; - newCloneBin.height = currentCloneBin.height; - } else { - currentCloneOpts.height = newCloneBin.height; - } - - currentClones.forEach(c => c.destroy()); - Utils.animate(currentCloneBin, currentCloneOpts); - } else if (animateSize) { - newCloneBin.width = 0; - newCloneBin.height = 0; - newCloneOpts.width = this.cloneWidth; - newCloneOpts.height = this.cloneHeight; - } - - Utils.animate(newCloneBin, newCloneOpts); - } - - _getWindowCloneBin(window) { - let frameRect = window.get_frame_rect(); - let bufferRect = window.get_buffer_rect(); - let clone = new Clutter.Clone({ source: window.get_compositor_private() }); - let cloneBin = new St.Widget({ - opacity: 0, - layout_manager: frameRect.width != bufferRect.width || - frameRect.height != bufferRect.height ? - new WindowCloneLayout(frameRect, bufferRect) : - new Clutter.BinLayout() - }); - - cloneBin.add_child(clone); - - return cloneBin; - } - - _getBinSize() { - let [fixedWidth, fixedHeight] = this._previewDimensions; - - return [ - aspectRatio.x.fixed ? fixedWidth + this._padding * 2 : -1, - aspectRatio.y.fixed ? fixedHeight + this._padding * 2 : -1 - ]; - } - - _resizeClone(cloneBin, window) { - let frameRect = cloneBin.layout_manager.frameRect || window.get_frame_rect(); - let [fixedWidth, fixedHeight] = this._previewDimensions; - let ratio = Math.min(fixedWidth / frameRect.width, fixedHeight / frameRect.height, 1); - let cloneWidth = frameRect.width * ratio; - let cloneHeight = frameRect.height * ratio; - - let clonePaddingTB = cloneHeight < MIN_DIMENSION ? MIN_DIMENSION - cloneHeight : 0; - let clonePaddingLR = cloneWidth < MIN_DIMENSION ? MIN_DIMENSION - cloneWidth : 0; - let clonePaddingTop = clonePaddingTB * .5; - let clonePaddingLeft = clonePaddingLR * .5; - - this.cloneWidth = cloneWidth + clonePaddingLR * scaleFactor; - this.cloneHeight = cloneHeight + clonePaddingTB * scaleFactor; - - cloneBin.set_style('padding: ' + clonePaddingTop + 'px ' + clonePaddingLeft + 'px;'); - cloneBin.layout_manager.ratio = ratio; - cloneBin.layout_manager.padding = [clonePaddingLeft * scaleFactor, clonePaddingTop * scaleFactor]; - - cloneBin.get_first_child().set_size(cloneWidth, cloneHeight); - } - - _getPreviewDimensions() { - let size = SETTINGS.get_int('window-preview-size') * scaleFactor; - let w, h; - - if (this._previewMenu.isVertical) { - w = size; - h = w * aspectRatio.y.size / aspectRatio.x.size; - } else { - h = size; - w = h * aspectRatio.x.size / aspectRatio.y.size; - } - - return [w, h]; - } -}); - -export const WindowCloneLayout = GObject.registerClass({ -}, class WindowCloneLayout extends Clutter.BinLayout { - - _init(frameRect, bufferRect) { - super._init(); - - //the buffer_rect contains the transparent padding that must be removed - this.frameRect = frameRect; - this.bufferRect = bufferRect; - } - - vfunc_allocate(actor, box) { - let [width, height] = box.get_size(); - - box.set_origin( - (this.bufferRect.x - this.frameRect.x) * this.ratio + this.padding[0], - (this.bufferRect.y - this.frameRect.y) * this.ratio + this.padding[1] - ); - - box.set_size( - width + (this.bufferRect.width - this.frameRect.width) * this.ratio, - height + (this.bufferRect.height - this.frameRect.height) * this.ratio - ); - - actor.get_first_child().allocate(box); - } -}); - -export function setStyle(actor, style) { - if (!isManualStyling) { - actor.set_style(style); - } -} - -export function getTweenOpts(opts) { - let defaults = { - time: animationTime, - transition: 'easeInOutQuad' - }; - - return Utils.mergeObjects(opts || {}, defaults); -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/askRenamePopup.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/askRenamePopup.js deleted file mode 100644 index e0b15f7..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/askRenamePopup.js +++ /dev/null @@ -1,120 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported AskRenamePopup */ -'use strict'; -const Gtk = imports.gi.Gtk; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; -const DBusUtils = imports.dbusUtils; -const DesktopIconsUtil = imports.desktopIconsUtil; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var AskRenamePopup = class { - constructor(fileItem, allowReturnOnSameName, closeCB) { - this._closeCB = closeCB; - this._allowReturnOnSameName = allowReturnOnSameName; - this._desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); - this._fileItem = fileItem; - this._popover = new Gtk.Popover({ - relative_to: fileItem._iconContainer, - modal: true, - }); - let contentBox = new Gtk.Grid({ - row_spacing: 6, - column_spacing: 6, - margin: 10, - }); - this._popover.add(contentBox); - let label = new Gtk.Label({ - label: fileItem.isDirectory ? _('Folder name') : _('File name'), - justify: Gtk.Justification.LEFT, - halign: Gtk.Align.START, - }); - contentBox.attach(label, 0, 0, 2, 1); - this._textArea = new Gtk.Entry(); - this._textArea.text = fileItem.fileName; - contentBox.attach(this._textArea, 0, 1, 1, 1); - this._button = new Gtk.Button({label: allowReturnOnSameName ? _('OK') : _('Rename')}); - contentBox.attach(this._button, 1, 1, 1, 1); - this._buttonId = this._button.connect('clicked', this._do_rename.bind(this)); - this._textAreaChangedId = this._textArea.connect('changed', this._validate.bind(this)); - this._textAreaActivateId = this._textArea.connect('activate', this._do_rename.bind(this)); - this._popoverId = this._popover.connect('closed', this._cleanAll.bind(this)); - this._textArea.set_can_default(true); - this._popover.set_default_widget(this._textArea); - this._button.get_style_context().add_class('suggested-action'); - contentBox.show_all(); - this._popover.popup(); - this._validate(); - this._textArea.grab_focus_without_selecting(); - this._textArea.select_region(0, DesktopIconsUtil.getFileExtensionOffset(fileItem.fileName, {'isDirectory': fileItem.isDirectory}).offset); - } - - _cleanAll() { - this._button.disconnect(this._buttonId); - this._textArea.disconnect(this._textAreaActivateId); - this._textArea.disconnect(this._textAreaChangedId); - this._popover.disconnect(this._popoverId); - this._closeCB(); - } - - updateFileItem(fileItem) { - this._fileItem = fileItem; - if (fileItem) { - this._popover.set_relative_to(this._fileItem._iconContainer); - this._popover.modal = true; - this._textArea.set_position(this._cursorPosition); - } else { - this._cursorPosition = this._textArea.get_position(); - this._popover.modal = false; - this._popover.set_relative_to(null); - } - } - - _validate() { - let text = this._textArea.text; - let finalPath = `${this._desktopPath}/${text}`; - let finalFile = Gio.File.new_for_commandline_arg(finalPath); - if ((text == '') || (text.indexOf('/') !== -1) || - ((text == this._fileItem.fileName) && !this._allowReturnOnSameName) || - (finalFile.query_exists(null) && (text !== this._fileItem.fileName))) { - this._button.sensitive = false; - } else { - this._button.sensitive = true; - } - } - - _do_rename() { - if (!this._button.sensitive) { - return; - } - this._popover.popdown(); - if (this._fileItem.fileName == this._textArea.text) { - return; - } - DBusUtils.RemoteFileOperations.RenameURIRemote( - this._fileItem.file.get_uri(), this._textArea.text - ); - } - - closeWindow() { - this._popover.popdown(); - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/autoAr.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/autoAr.js deleted file mode 100644 index e09013c..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/autoAr.js +++ /dev/null @@ -1,774 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2022 Sergio Costas (sergio.costas@canonical.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const GLib = imports.gi.GLib; -const Gio = imports.gi.Gio; -const Gtk = imports.gi.Gtk; -var GnomeAutoar = null; -try { - GnomeAutoar = imports.gi.GnomeAutoar; -} catch (e) { -} - -const Enums = imports.enums; -const FileUtils = imports.fileUtils; -const Prefs = imports.preferences; -const Signals = imports.signals; - -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var AutoAr = class { - constructor(desktopManager) { - this._desktopManager = desktopManager; - this._progressWindow = new Gtk.Window({ - title: 'Archives Operations', - resizable: false, - deletable: false, - modal: false, - default_height: 100, - window_position: Gtk.WindowPosition.CENTER_ALWAYS, - }); - this._progressWindow.connect('delete-event', () => { - return true; - }); - this._progressContainer = new Gtk.Box({ - spacing: 12, - margin_top: 15, - margin_bottom: 15, - margin_start: 30, - margin_end: 30, - halign: Gtk.Align.CENTER, - orientation: Gtk.Orientation.VERTICAL, - }); - this._inhibitCookie = null; - this._progressContainer.connect('remove', () => { - this._progressElements--; - if (this._progressElements == 0) { - this._progressWindow.hide(); - if (this._inhibitCookie !== null) { - this._desktopManager.mainApp.uninhibit(this._inhibitCookie); - this._inhibitCookie = null; - } - } - - this.emit('progress-elements-changed', this._progressElements); - }); - this._progressElements = 0; - const scroll = new Gtk.ScrolledWindow({ - propagate_natural_width: true, - min_content_height: 300, - }); - scroll.hscrollbar_policy = Gtk.PolicyType.NEVER; - scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; - this._progressWindow.add(scroll); - const viewport = new Gtk.Viewport(); - scroll.add(viewport); - viewport.add(this._progressContainer); - this._refreshExtensions(); - } - - checkAutoAr() { - if (GnomeAutoar === null) { - this._desktopManager.dbusManager.doNotify(_('AutoAr is not installed'), - _('To be able to work with compressed files, install file-roller and/or gir-1.2-gnomeAutoAr')); - } - return GnomeAutoar !== null; - } - - _refreshExtensions() { - this._formats = []; - this._filters = []; - this._extensions = {}; - this._combinedExtensions = {}; - if (!GnomeAutoar) { - return; - } - const lastFormat = GnomeAutoar.format_last(); - const lastFilter = GnomeAutoar.filter_last(); - for (let format = 0; format <= lastFormat; format++) { - try { - if (!GnomeAutoar.format_is_valid(format)) { - continue; - } - } catch (e) { - continue; - } - this._formats.push(format); - const extension = GnomeAutoar.format_get_extension(format); - if (!extension) { - continue; - } - this._extensions[extension] = { - extension, - format, - filter: null, - }; - } - for (let filter = 0; filter <= lastFilter; filter++) { - try { - if (!GnomeAutoar.filter_is_valid(filter)) { - continue; - } - } catch (e) { - continue; - } - this._filters.push(filter); - const extension = GnomeAutoar.filter_get_extension(filter); - if (!extension) { - continue; - } - this._extensions[extension] = { - extension, - format: null, - filter, - }; - } - for (let format of this._formats) { - for (let filter of this._filters) { - const extension = GnomeAutoar.format_filter_get_extension(format, filter); - if (!extension) { - continue; - } - this._combinedExtensions[extension] = { - extension, - format, - filter, - }; - } - } - } - - extensionIsAvailable(extension) { - return (extension in this._extensions) || (extension in this._combinedExtensions); - } - - getFormatAndFilterForExtension(extension) { - if (extension in this._extensions) { - return this._extensions[extension]; - } - if (extension in this._combinedExtensions) { - return this._combinedExtensions[extension]; - } - return null; - } - - _getFormatAndFilterForFilename(fileName) { - for (let extension in this._combinedExtensions) { - if (fileName.endsWith(`.${extension}`)) { - return this._combinedExtensions[extension]; - } - } - for (let extension in this._extensions) { - if (fileName.endsWith(`.${extension}`)) { - return this._extensions[extension]; - } - } - return null; - } - - fileIsCompressed(fileName) { - return this._getFormatAndFilterForFilename(fileName) !== null; - } - - runToolAsync(autoArTool, cancellable) { - return new Promise((resolve, reject) => { - const connections = []; - - connections.push(autoArTool.connect('cancelled', () => { - connections.forEach(c => autoArTool.disconnect(c)); - reject(new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.CANCELLED, - 'Operation was cancelled')); - })); - - connections.push(autoArTool.connect('error', (w, error) => { - connections.forEach(c => autoArTool.disconnect(c)); - reject(error); - })); - - connections.push(autoArTool.connect('completed', () => { - connections.forEach(c => autoArTool.disconnect(c)); - resolve(); - })); - - autoArTool.start_async(cancellable); - }); - } - - extractFile(fileName) { - if (!this.checkAutoAr()) { - return; - } - const fullPath = GLib.build_filenamev([GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP), fileName]); - const formatFilter = this._getFormatAndFilterForFilename(fileName); - const extSize = formatFilter.extension.length; - const total = fullPath.length; - const folderName = fullPath.substring(0, total - extSize); - const folder = Gio.File.new_for_path(folderName); - const doExtract = new progressDialog(this, _('Extracting files')); - this._password = null; - doExtract.doExtractFile(fullPath, folder, folderName).catch( - e => logError(e)); - } - - compressFileItems(fileList, destinationFolder) { - if (!this.checkAutoAr()) { - return; - } - new CompressDialog(this._desktopManager, fileList, destinationFolder); - } - - compressFiles(fileList, outputFile, format, filter, password = null) { - if (!this.checkAutoAr()) { - return; - } - const doCompress = new progressDialog(this, _('Compressing files')); - doCompress.doCompressFiles(fileList, outputFile, format, filter, password).catch( - e => logError(e)); - } - - notify(title, text) { - this._desktopManager.dbusManager.doNotify(title, text); - } - - getProgressElements() { - return this._progressContainer.get_children(); - } - - addProgress(progressElement, message) { - this._progressContainer.pack_start(progressElement, false, true, 0); - if (this._progressElements == 0) { - this._inhibitCookie = this._desktopManager.mainApp.inhibit(null, - Gtk.ApplicationInhibitFlags.LOGOUT | Gtk.ApplicationInhibitFlags.SUSPEND, - message); - } - this._progressElements++; - this._progressWindow.show_all(); - this._progressWindow.present(); - this.emit('progress-elements-changed', this._progressElements); - } -}; - -Signals.addSignalMethods(AutoAr.prototype); - -const progressDialog = class { - constructor(autoArClass, message) { - this._autoAr = autoArClass; - this._waitingForPassword = false; - this._currentPassword = null; - this._buttonPromiseAccept = null; - this._container = new Gtk.Box({ - spacing: 0, - halign: Gtk.Align.END, - orientation: Gtk.Orientation.VERTICAL, - }); - this._processLabel = new Gtk.Label(); - this._processBar = new Gtk.ProgressBar(); - const container2 = new Gtk.Box({ - spacing: 12, - margin_top: 15, - margin_bottom: 15, - margin_start: 30, - margin_end: 30, - halign: Gtk.Align.CENTER, - orientation: Gtk.Orientation.HORIZONTAL, - }); - const container3 = new Gtk.Box({ - spacing: 10, - halign: Gtk.Align.END, - orientation: Gtk.Orientation.VERTICAL, - }); - this._cancelButton = new Gtk.Button({label: _('Cancel')}); - this._cancelButton.connect('clicked', () => { - if (this._buttonPromiseAccept) { - this._buttonPromiseAccept(false); - return; - } - this._cancellable.cancel(); - }); - this._passOkButton = new Gtk.Button({label: _('OK')}); - this._passOkButton.get_style_context().add_class('suggested-action'); - const passOKfunc = function () { - this._processBar.show(); - this._passEntry.hide(); - this._passOkButton.hide(); - this._currentPassword = this._passEntry.get_text(); - if (this._buttonPromiseAccept) { - this._buttonPromiseAccept(true); - } - }.bind(this); - this._passOkButton.connect('clicked', passOKfunc); - this._passEntry = new Gtk.Entry({ - placeholder_text: _('Enter a password here'), - input_purpose: Gtk.InputPurpose.PASSWORD, - visibility: false, - secondary_icon_name: 'view-conceal', - secondary_icon_activatable: true, - secondary_icon_sensitive: true, - }); - container3.pack_start(this._processLabel, false, true, 0); - container3.pack_start(this._processBar, false, true, 0); - container3.pack_start(this._passEntry, false, true, 0); - container2.pack_start(container3, false, true, 0); - container2.pack_start(this._passOkButton, false, false, 0); - container2.pack_start(this._cancelButton, false, false, 0); - this._container.pack_start(container2, false, false, 0); - this._passEntry.connect('icon-release', () => { - this._passEntry.visibility = !this._passEntry.visibility; - }); - this._passEntry.connect('activate', passOKfunc); - - const separator = new Gtk.Separator({orientation: Gtk.Orientation.HORIZONTAL}); - this._container.pack_start(separator, false, true, 4); - const updateSeparatorVisibility = () => { - const progressElements = this._autoAr.getProgressElements(); - separator.visible = progressElements.length && - this._container != progressElements[progressElements.length - 1]; - }; - updateSeparatorVisibility(); - this._elementsChangedId = this._autoAr.connect('progress-elements-changed', - updateSeparatorVisibility); - - this._cancellable = new Gio.Cancellable(); - this._autoAr.addProgress(this._container, message); - this._passEntry.hide(); - this._passOkButton.hide(); - } - - async _cleanupFile(file, cancellable) { - if (!file.query_exists(null)) { - return; - } - this._processBar.set_fraction(0); - this._processLabel.set_label(_("Removing partial file '${outputFile}'").replace( - '${outputFile}', file.get_basename())); - - this._removeTimer(); - this._timer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { - this._processBar.pulse(); - return true; - }); - - try { - await FileUtils.deleteFile(file, null, cancellable); - } catch (e) { - logError(e, `Failed to remove ${file.get_path()}: ${e.message}`); - } finally { - this._removeTimer(); - } - } - - async doExtractFile(fullPath, folder, folderName, counter = 1) { - this._processLabel.set_label(_('Creating destination folder')); - this._processBar.pulse(); - - try { - await folder.make_directory_async_promise(GLib.PRIORITY_DEFAULT, this._cancellable); - - const info = new Gio.FileInfo(); - info.set_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE, 0o700); - - try { - await folder.set_attributes_async_promise(info, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - this._cancellable); - } catch (e) { - logError(e, `Failed to set attributes to ${folder.get_path()}`); - } - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - this._destroy(); - return; - } - - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) { - const newFolder = Gio.File.new_for_path(`${folderName} (${counter})`); - await this.doExtractFile(fullPath, newFolder, folderName, counter + 1); - return; - } - - throw e; - } - - this._processLabel.set_label(_("Extracting files into '${outputPath}'").replace( - '${outputPath}', folder.get_basename())); - - const fullPathFile = Gio.File.new_for_path(fullPath); - const extractor = GnomeAutoar.Extractor.new(fullPathFile, folder); - extractor.set_output_is_dest(true); - if (extractor.set_passphrase && (this._currentPassword !== null)) { - extractor.set_passphrase(this._currentPassword); - } - - this._removeTimer(); - this._timer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { - this._processBar.pulse(); - return true; - }); - - let progressTotal = -1; - const progressID = extractor.connect('progress', (w, completedSize) => { - this._removeTimer(); - - if (progressTotal <= 0) { - progressTotal = extractor.get_total_size(); - } - - if (progressTotal > 0) { - this._processBar.set_fraction(completedSize / progressTotal); - } - }); - - try { - await this._autoAr.runToolAsync(extractor, this._cancellable); - - this._autoAr.notify(_('Extraction completed'), - _("Extracting '${fullPathFile}' has been completed.").replace( - '${fullPathFile}', fullPathFile.get_basename())); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - this._cancellable = new Gio.Cancellable(); - await this._cleanupFile(folder, this._cancellable); - this._autoAr.notify(_('Extraction cancelled'), - _("Extracting '${fullPathFile}' has been cancelled by the user.").replace( - '${fullPathFile}', fullPathFile.get_basename())); - } else { - if ((e.code == GnomeAutoar.PASSPHRASE_REQUIRED_ERRNO) && (e.domain == GnomeAutoar.Extractor.quark())) { - this._waitingForPassword = true; - this._processBar.hide(); - this._passEntry.show(); - this._passOkButton.show(); - this._passOkButton.set_receives_default(true); - const tmpfile = Gio.File.new_for_path(fullPath); - this._processLabel.set_label(_('Passphrase required for ${filename}').replace('${filename}', tmpfile.get_basename())); - } else { - this._waitingForPassword = false; - this._autoAr.notify(_('Error during extraction'), e.message); - } - await this._cleanupFile(folder, this._cancellable); - } - } finally { - this._removeTimer(); - extractor.disconnect(progressID); - if (!this._waitingForPassword) { - this._destroy(); - } - } - if (this._waitingForPassword) { - const retval = await this._waitButtons(); - this._buttonPromiseAccept = null; - this._waitingForPassword = false; - if (retval) { - await this.doExtractFile(fullPath, folder, folderName); - } - } - } - - _waitButtons() { - return new Promise(accept => { - this._buttonPromiseAccept = accept; - }); - } - - async doCompressFiles(fileList, outputFile, format, filter, password = null) { - const output = Gio.File.new_for_path(outputFile); - this._processLabel.set_label(_("Compressing files into '${outputFile}'").replace( - '${outputFile}', output.get_basename())); - const compressor = GnomeAutoar.Compressor.new(fileList, output, format, filter, false); - compressor.set_output_is_dest(true); - if (password) { - compressor.set_passphrase(password); - } - - const progressID = compressor.connect('progress', () => this._processBar.pulse()); - - try { - await this._autoAr.runToolAsync(compressor, this._cancellable); - - this._autoAr.notify(_('Compression completed'), - _("Compressing files into '${outputFile}' has been completed.").replace( - '${outputFile}', output.get_basename())); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) { - this._autoAr.notify(_('Cancelled compression'), - _("The output file '${outputFile}' already exists.").replace( - '${outputFile}', output.get_basename())); - } else { - this._cancellable = new Gio.Cancellable(); - await this._cleanupFile(output, this._cancellable); - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - this._autoAr.notify(_('Cancelled compression'), - _("Compressing files into '${outputFile}' has been cancelled by the user.").replace( - '${outputFile}', output.get_basename())); - } else { - this._autoAr.notify(_('Error during compression'), e.message); - } - } - } finally { - compressor.disconnect(progressID); - this._destroy(); - } - } - - _removeTimer() { - if (this._timer) { - GLib.source_remove(this._timer); - this._timer = 0; - } - } - - _destroy() { - this._autoAr.disconnect(this._elementsChangedId); - this._cancellable.cancel(); - this._container.destroy(); - } -}; - - -const CompressDialog = class { - constructor(desktopManager, fileList, destinationFolder) { - this._fileList = []; - for (let file of fileList) { - this._fileList.push(file.file); - } - this._desktopManager = desktopManager; - this._destinationFolder = destinationFolder; - this._dialog = new Gtk.Dialog({ - title: _('Create archive'), - resizable: false, - modal: true, - use_header_bar: true, - default_width: 500, - default_height: 210, - window_position: Gtk.WindowPosition.CENTER_ALWAYS, - }); - const container = this._dialog.get_content_area(); - container.orientation = Gtk.Orientation.VERTICAL; - container.margin_top = 30; - container.margin_bottom = 30; - container.margin_start = 30; - container.margin_end = 30; - container.width_request = 390; - container.halign = Gtk.Align.CENTER; - container.spacing = 6; - - if (Prefs.nautilusCompression) { - this._selectedType = Prefs.nautilusCompression.get_enum('default-compression-format'); - } else { - this._selectedType = Enums.CompressionType.ZIP; - } - - const archiveLabel = new Gtk.Label({ - label: `${_('Archive name')}`, - xalign: 0, - use_markup: true, - }); - container.pack_start(archiveLabel, false, true, 0); - const box1 = new Gtk.Box({ - spacing: 12, - orientation: Gtk.Orientation.HORIZONTAL, - }); - this._nameEntry = new Gtk.Entry({ - hexpand: true, - width_chars: 30, - }); - - this._extensionDropdown = new Gtk.Button(); - const extensionContainer = new Gtk.Box({ - spacing: 2, - orientation: Gtk.Orientation.HORIZONTAL, - }); - this._extensionLabel = new Gtk.Label(); - this._extensionLock = new Gtk.Image({icon_name: 'dialog-password'}); - extensionContainer.pack_start(this._extensionLabel, false, false, 0); - extensionContainer.pack_start(this._extensionLock, false, false, 5); - this._extensionDropdown.add(extensionContainer); - this._extensionPopover = new Gtk.Popover({ - relative_to: this._extensionDropdown, - border_width: 8, - }); - this._extensionPopoverContainer = new Gtk.Box({ - spacing: 4, - orientation: Gtk.Orientation.VERTICAL, - }); - this._extensionPopover.add(this._extensionPopoverContainer); - - this._passLabel = new Gtk.Label({ - label: _('Password'), - margin_top: 6, - xalign: 0, - }); - this._passEntry = new Gtk.Entry({ - placeholder_text: _('Enter a password here'), - input_purpose: Gtk.InputPurpose.PASSWORD, - visibility: false, - secondary_icon_name: 'view-conceal', - secondary_icon_activatable: true, - secondary_icon_sensitive: true, - }); - - container.pack_start(box1, false, true, 0); - box1.pack_start(this._nameEntry, false, true, 0); - box1.pack_start(this._extensionDropdown, false, false, 0); - container.pack_start(this._passLabel, false, false, 0); - container.pack_start(this._passEntry, false, false, 0); - - this._okButton = this._dialog.add_button(_('Create'), Gtk.ResponseType.ACCEPT); - this._okButton.get_style_context().add_class('suggested-action'); - this._okButton.set_receives_default(true); - this._cancelButton = this._dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - this._cancelButton.set_receives_default(true); - this._fillComboBox(); - this._dialog.show_all(); - this._updateStatus(); - this._extensionDropdown.connect('clicked', () => { - this._extensionPopoverContainer.show_all(); - this._extensionPopover.popup(); - for (let index in this._compressOptions) { - const data = this._compressOptions[index]; - data.selected_icon.visible = index == this._selectedType; - } - }); - this._nameEntry.connect('changed', () => this._updateStatus()); - this._passEntry.connect('changed', () => this._updateStatus()); - this._nameEntry.connect('activate', () => this._entryActivated()); - this._passEntry.connect('activate', () => this._entryActivated()); - this._passEntry.connect('icon-release', () => { - this._passEntry.visibility = !this._passEntry.visibility; - }); - this._dialog.connect('response', (dialog, id) => { - if (id === Gtk.ResponseType.ACCEPT) { - const data = this._desktopManager.autoAr.getFormatAndFilterForExtension(this._compressOptions[this._selectedType].extension); - const outputFile = GLib.build_filenamev([this._destinationFolder, this._nameEntry.get_text() + data.extension]); - const password = this._passEntry.get_text(); - this._desktopManager.autoAr.compressFiles(this._fileList, outputFile, data.format, data.filter, password); - } - this._dialog.close(); - }); - } - - _entryActivated() { - this._updateStatus(); - if (this._okButton.sensitive) { - this._dialog.response(Gtk.ResponseType.ACCEPT); - } - } - - _updateStatus() { - if (Prefs.nautilusCompression) { - Prefs.nautilusCompression.set_enum('default-compression-format', this._selectedType); - } - const label = this._compressOptions[this._selectedType].extension; - this._extensionLabel.label = label; - this._extensionLock.visible = this._compressOptions[this._selectedType].password; - const password = this._compressOptions[this._selectedType].password; - const outputfile = this._nameEntry.get_text() + label; - this._passLabel.visible = password; - this._passEntry.visible = password; - let context = this._nameEntry.get_style_context(); - this._okButton.sensitive = true; - if (this._desktopManager._fileList.map(f => f.fileName).includes(outputfile)) { - this._okButton.sensitive = false; - if (!context.has_class('not-found')) { - context.add_class('not-found'); - } - } else if (context.has_class('not-found')) { - context.remove_class('not-found'); - } - if (password && (this._passEntry.get_text_length() == 0)) { - this._okButton.sensitive = false; - } - if (this._nameEntry.get_text_length() == 0) { - this._okButton.sensitive = false; - } - } - - _fillComboBox() { - this._compressOptions = {}; - this._addComboEntry(Enums.CompressionType.ZIP, { - extension: '.zip', - id: 'zip', - description: _('Compatible with all operating systems.'), - password: false, - }); - this._addComboEntry(Enums.CompressionType.ENCRYPTED_ZIP, { - extension: '.zip', - id: 'encryptedzip', - description: _('Password protected .zip, must be installed on Windows and Mac.'), - password: true, - }); - this._addComboEntry(Enums.CompressionType.TAR_XZ, { - extension: '.tar.xz', - id: 'tar.xz', - description: _('Smaller archives but Linux and Mac only.'), - password: false, - }); - this._addComboEntry(Enums.CompressionType.SEVEN_ZIP, { - extension: '.7z', - id: '7z', - description: _('Smaller archives but must be installed on Windows and Mac.'), - password: false, - }); - } - - _addComboEntry(type, data) { - this._compressOptions[type] = data; - if (!this._desktopManager.autoAr.extensionIsAvailable(data.extension)) { - return; - } - const container = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL}); - const container2 = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL}); - const container3 = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL}); - container3.pack_start(new Gtk.Label({ - label: data.extension, - justify: Gtk.Justification.LEFT, - xalign: 0, - }), - false, - false, - 0); - if (data.password) { - container3.pack_start(new Gtk.Image({icon_name: 'dialog-password'}), - false, - false, - 5); - } - container.pack_start(container3, false, false, 0); - container.pack_start(new Gtk.Label({ - label: data.description, - justify: Gtk.Justification.LEFT, - xalign: 0, - }), - false, - false, - 0); - const button = new Gtk.Button(); - container2.pack_start(container, true, true, 0); - data.selected_icon = new Gtk.Image({icon_name: 'emblem-default'}); - container2.pack_start(data.selected_icon, false, false, 0); - button.add(container2); - this._extensionPopoverContainer.pack_start(button, false, true, 0); - button.connect('clicked', () => { - this._selectedType = type; - this._extensionPopover.popdown(); - this._updateStatus(); - }); - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/createThumbnail.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/createThumbnail.js deleted file mode 100755 index 613423b..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/createThumbnail.js +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/gjs - -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -imports.gi.versions.GnomeDesktop = '3.0'; -const GnomeDesktop = imports.gi.GnomeDesktop; -const Gio = imports.gi.Gio; - -/** - * - */ -function CreateThumbnail() { - let thumbnailFactoryNormal = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.NORMAL); - let thumbnailFactoryLarge = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE); - - let file = Gio.File.new_for_path(ARGV[0]); - if (!file.query_exists(null)) { - return 1; - } - - let fileUri = file.get_uri(); - let fileInfo = file.query_info('standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null); - let modifiedTime = fileInfo.get_attribute_uint64('time::modified'); - - // check if the thumbnail has been already created in the meantime by another program - let thumbnailLarge = thumbnailFactoryLarge.lookup(fileUri, modifiedTime); - if (thumbnailLarge != null) { - return 3; - } - let thumbnailNormal = thumbnailFactoryNormal.lookup(fileUri, modifiedTime); - if (thumbnailNormal != null) { - return 3; - } - if (thumbnailFactoryNormal.has_valid_failed_thumbnail(fileUri, modifiedTime)) { - return 4; - } - - // now, generate the file - let thumbnailPixbuf = thumbnailFactoryLarge.generate_thumbnail(fileUri, fileInfo.get_content_type()); - if (thumbnailPixbuf == null) { - thumbnailFactoryLarge.create_failed_thumbnail(fileUri, modifiedTime); - return 2; - } else { - thumbnailFactoryLarge.save_thumbnail(thumbnailPixbuf, fileUri, modifiedTime); - return 0; - } -} - -CreateThumbnail(); diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusInterfaces.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusInterfaces.js deleted file mode 100644 index 09acc66..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusInterfaces.js +++ /dev/null @@ -1,225 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2022 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported DBusInterfaces */ -'use strict'; -var DBusInterfaces = { - // net.haddes.SwitcherooControl - 'net.hadess.SwitcherooControl': ` - - - - - - `, - - // org.freedesktop.FileManager1 - 'org.freedesktop.FileManager1': ` - - - - - - - - - - - `, - - // org.gnome.ArchiveManager1 - 'org.gnome.ArchiveManager1': ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - - // org.gnome.Nautilus.FileOperations2 - 'org.gnome.Nautilus.FileOperations2': ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - - // org.gnome.NautilusPreviewer - 'org.gnome.NautilusPreviewer': ` - - - - - - - - `, - - // org.gtk.vfs.Metadata - 'org.gtk.vfs.Metadata': ` - - - - - - - - - - - - - - - - - - - - - - - - - - `, - - // org.freedesktop.DBus.Introspectable - 'org.freedesktop.DBus.Introspectable': ` - - - - - - `, - - // org.freedesktop.Notifications - 'org.freedesktop.Notifications': ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -`, -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusUtils.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusUtils.js deleted file mode 100644 index b3e2171..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/dbusUtils.js +++ /dev/null @@ -1,1012 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019-2022 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported GtkVfsMetadata, extensionControl, discreteGpuAvailable, RemoteFileOperations, init */ -'use strict'; -const {Gio, GLib, Gdk, Gtk} = imports.gi; -const Signals = imports.signals; -const DBusInterfaces = imports.dbusInterfaces; -const DesktopIconsUtil = imports.desktopIconsUtil; - -var NautilusFileOperations2 = null; -var FreeDesktopFileManager = null; -var GnomeNautilusPreview = null; -var SwitcherooControl = null; -var GnomeArchiveManager = null; -var GtkVfsMetadata = null; -var extensionControl = null; - -var discreteGpuAvailable = false; -var dbusManagerObject; -var RemoteFileOperations; - -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -class ProxyManager { - /* - * This class manages a DBus object through a DBusProxy. Any access to the proxy when the - * object isn't available results in a notification specifying that an specific program - * is needed to run that option. - * - * The proxy itself is accessed through the 'proxy' property (read-only). Any access to - * it will check the availability and show the notification if it isn't available. To get - * access to it without triggering this, it is possible to use the 'proxyNoCheck' property. - * - * Whether the object is or not available can be checked with the 'isAvailable' property. - * Also, every time the availability changes, the signal 'changed-status' is emitted. - */ - constructor(dbusManager, serviceName, objectName, interfaceName, inSystemBus, programNeeded) { - this._dbusManager = dbusManager; - this._serviceName = serviceName; - this._objectName = objectName; - this._interfaceName = interfaceName; - this._inSystemBus = inSystemBus; - this._signals = {}; - this._signalsIDs = {}; - this._connectSignals = {}; - this._connectSignalsIDs = {}; - this._beingLaunched = false; - if (typeof programNeeded == 'string') { - // if 'programNeeded' is a string, create a generic message for the notification. - this._programNeeded = [ - _('"${programName}" is needed for Desktop Icons').replace('${programName}', programNeeded), - _('For this functionality to work in Desktop Icons, you must install "${programName}" in your system.').replace('${programName}', programNeeded), - programNeeded, - ]; - } else { - // instead, if it's not, it is presumed to be an array with two sentences, one for the notification title and another for the main text. - this._programNeeded = programNeeded; - } - this._timeout = 0; - this._available = false; - this._proxy = null; - if (this._dbusManager.checkIsAvailable(this._serviceName, this._inSystemBus)) { - this.makeNewProxy(); - } - dbusManager.connect(inSystemBus ? 'changed-availability-system' : 'changed-availability-local', () => { - const newAvailability = this._dbusManager.checkIsAvailable(this._serviceName, this._inSystemBus); - if (newAvailability != this._available) { - if (newAvailability) { - this.makeNewProxy(); - } else { - this._available = false; - this._proxy = null; - this.emit('changed-status', false); - } - } - }); - } - - connectSignalToProxy(signal, cb) { - this._connectSignals[signal] = cb; - if (this._proxy) { - this._connectSignalsIDs[signal] = this._proxy.connectSignal(signal, cb); - } - } - - connectToProxy(signal, cb) { - this._signals[signal] = cb; - if (this._proxy) { - this._signalsIDs[signal] = this._proxy.connect(signal, cb); - } - } - - disconnectFromProxy(signal) { - if (signal in this._signalsIDs) { - if (this._proxy) { - this._proxy.disconnect(this._signalsIDs[signal]); - } - delete this._signalsIDs[signal]; - } - } - - disconnectSignalFromProxy(signal) { - if (signal in this._connectSignalsIDs) { - if (this._proxy) { - this._proxy.disconnectSignal(this._connectSignalsIDs[signal]); - } - delete this._connectSignalsIDs[signal]; - } - } - - async makeNewProxy(delay = 0) { - if (delay !== 0) { - await DesktopIconsUtil.waitDelayMs(delay); - if (!this._dbusManager.checkIsAvailable(this._serviceName, this._inSystemBus)) { - return; - } - } - if (this._beingLaunched) { - return; - } - this._interfaceXML = this._dbusManager.getInterface(this._serviceName, this._objectName, this._interfaceName, this._inSystemBus, false); - if (this._interfaceXML) { - this._beingLaunched = true; - try { - new Gio.DBusProxy.makeProxyWrapper(this._interfaceXML)( - this._inSystemBus ? Gio.DBus.system : Gio.DBus.session, - this._serviceName, - this._objectName, - (proxy, error) => { - this._beingLaunched = false; - if (error === null) { - for (let signal in this._signals) { - this._signalsIDs[signal] = proxy.connect(signal, this._signals[signal]); - } - for (let signal in this._connectSignals) { - this._connectSignalsIDs[signal] = proxy.connectSignal(signal, this._connectSignals[signal]); - } - this._available = true; - this._proxy = proxy; - print(`DBus interface for ${this._programNeeded[2]} (${this._interfaceName}) is now available.`); - this.emit('changed-status', true); - } else { - logError(error, `Error creating proxy, ${this._programNeeded[2]} (${this._interfaceName}); relaunching.\n`); - this.makeNewProxy(1000); - } - } - ); - } catch (e) { - logError(e, `Error creating proxy, ${this._programNeeded[0]}`); - this._beingLaunched = false; - this.makeNewProxy(1000); - } - } - } - - get isAvailable() { - return this._available; - } - - get proxyNoCheck() { - return this._proxy; - } - - get proxy() { - if (!this._available) { - if (this._programNeeded && (this._timeout == 0)) { - print(this._programNeeded[0]); - print(this._programNeeded[1]); - this._dbusManager.doNotify(this._programNeeded[0], this._programNeeded[1]); - this._timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - 1000, - () => { - this._timeout = 0; - return false; - } - ); - } - } - return this._proxy; - } -} -Signals.addSignalMethods(ProxyManager.prototype); - - -class DBusManager { - /* - * This class manages all the DBus operations. A ProxyManager() class can subscribe to this to be notified - * whenever a change in the bus has occurred (like a server has been added or removed). It also can ask - * for a DBus interface, either getting it from the dbusInterfaces.js file or using DBus Introspection (which - * allows to get the currently available interface and, that way, know if an object implements an specific - * method, property or signal). - * - * ProxyManager() classes subscribe to the 'changed-availability-system' or 'changed-availability-local' signals, - * which are emitted every time a change in the bus or in the configuration files happen. Then, it can use - * checkIsAvailable() to determine if the desired service is available in the system or not. - */ - constructor() { - this._availableInSystemBus = []; - this._availableInLocalBus = []; - this._pendingLocalSignal = false; - this._pendingSystemSignal = false; - this._signalTimerID = 0; - - let interfaceXML = this.getInterface( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', - true, // system bus - true); // use DBus Introspection - this._dbusSystemProxy = new Gio.DBusProxy.makeProxyWrapper(interfaceXML)( - Gio.DBus.system, - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - null - ); - let ASCinSystemBus = interfaceXML.includes('ActivatableServicesChanged'); - - // Don't presume that both system and local have the same interface (just in case) - interfaceXML = this.getInterface( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', - false, // local bus - true); // use DBus Introspection - this._dbusLocalProxy = new Gio.DBusProxy.makeProxyWrapper(interfaceXML)( - Gio.DBus.session, - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - null - ); - let ASCinLocalBus = interfaceXML.includes('ActivatableServicesChanged'); - - this._updateAllAvailabilities(); - this._dbusLocalProxy.connectSignal('NameOwnerChanged', () => { - this._emitChangedSignal(true); - }); - if (ASCinLocalBus) { - this._dbusLocalProxy.connectSignal('ActivatableServicesChanged', () => { - this._emitChangedSignal(true); - }); - } - this._dbusSystemProxy.connectSignal('NameOwnerChanged', () => { - this._emitChangedSignal(false); - }); - if (ASCinSystemBus) { - this._dbusSystemProxy.connectSignal('ActivatableServicesChanged', () => { - this._emitChangedSignal(false); - }); - } - - interfaceXML = this.getInterface( - 'org.freedesktop.Notifications', - '/org/freedesktop/Notifications', - 'org.freedesktop.Notifications', - false, // local bus - false); // get interface from local code - this._notifyProxy = new Gio.DBusProxy.makeProxyWrapper(interfaceXML)( - Gio.DBus.session, - 'org.freedesktop.Notifications', - '/org/freedesktop/Notifications', - null - ); - } - - _emitChangedSignal(localDBus) { - if (localDBus) { - this._pendingLocalSignal = true; - } else { - this._pendingSystemSignal = true; - } - if (this._signalTimerID) { - GLib.source_remove(this._signalTimerID); - } - this._signalTimerID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => { - this._signalTimerID = 0; - this._updateAllAvailabilities(); - if (this._pendingLocalSignal) { - this.emit('changed-availability-local'); - } - if (this._pendingSystemSignal) { - this.emit('changed-availability-system'); - } - this._pendingLocalSignal = false; - this._pendingSystemSignal = false; - return false; - }); - } - - checkIsAvailable(serviceName, inSystemBus) { - if (inSystemBus) { - return this._availableInSystemBus.includes(serviceName); - } else { - return this._availableInLocalBus.includes(serviceName); - } - } - - _updateAllAvailabilities() { - this._availableInLocalBus = this._updateAvailability(this._dbusLocalProxy); - this._availableInSystemBus = this._updateAvailability(this._dbusSystemProxy); - } - - _updateAvailability(proxy) { - // We read both the well-known names actually running and those available as activatables, - // and generate a single list with both. Thus a service will be "enabled" if it is running - // or if it is activatable. - - let availableNames = []; - let names = proxy.ListNamesSync(); - for (let n of names[0]) { - if (n.startsWith(':')) { - continue; - } - if (!(n in availableNames)) { - availableNames.push(n); - } - } - let names2 = proxy.ListActivatableNamesSync(); - for (let n of names2[0]) { - if (n.startsWith(':')) { - continue; - } - if (!(n in availableNames)) { - availableNames.push(n); - } - } - return availableNames; - } - - _getNextTag() { - this._xmlIndex++; - let pos = this._xmlData.indexOf('<', this._xmlIndex); - if (pos == -1) { - return null; - } - let pos2 = this._xmlData.indexOf('>', pos); - if (pos2 == -1) { - return null; - } - this._xmlIndex = pos; - return this._xmlData.substring(pos + 1, pos2).trim(); - } - - /* - * Extracts the XML definition for an interface from the raw data returned by DBus Introspection. - * This is needed because DBus Introspection returns a single XML file with all the interfaces - * supported by an object, while DBusProxyWrapper requires an XML with only the desired interface. - */ - _parseXML(data, interfaceName) { - this._xmlIndex = -1; - this._xmlData = data; - let tag; - while (true) { - tag = this._getNextTag(); - if (tag === null) { - return null; - } - if (!tag.startsWith('interface ')) { - continue; - } - if (tag.includes(interfaceName)) { - break; - } - } - let start = this._xmlIndex; - while (true) { - tag = this._getNextTag(); - if (tag === null) { - return null; - } - if (!tag.startsWith('/interface')) { - continue; - } - break; - } - return `\n ${data.substring(start, 1 + data.indexOf('>', this._xmlIndex))}\n`; - } - - getInterface(serviceName, objectName, interfaceName, inSystemBus, forceIntrospection) { - if ((interfaceName in DBusInterfaces.DBusInterfaces) && !forceIntrospection) { - return DBusInterfaces.DBusInterfaces[interfaceName]; - } else { - let data = this.getIntrospectionData(serviceName, objectName, inSystemBus); - if (data == null) { - return null; - } else { - return this._parseXML(data, interfaceName); - } - } - } - - getIntrospectionData(serviceName, objectName, inSystemBus) { - let wraper = new Gio.DBusProxy.makeProxyWrapper(DBusInterfaces.DBusInterfaces['org.freedesktop.DBus.Introspectable'])( - inSystemBus ? Gio.DBus.system : Gio.DBus.session, - serviceName, - objectName, - null - ); - let data = null; - try { - data = wraper.IntrospectSync()[0]; - } catch (e) { - logError(e, 'Error getting introspection data over Dbus.'); - } - if (data == null) { - return null; - } - if (!data.includes('interface')) { - return null; // if it doesn't exist, return null - } - return data; - } - - doNotify(header, text) { - /* - * The notification interface in GLib.Application requires a .desktop file, which - * we can't have, so we must use directly the Notification DBus interface - */ - this._notifyProxy.NotifyRemote('', 0, '', header, text, [], {}, -1, () => {}); - } -} -Signals.addSignalMethods(DBusManager.prototype); - - -class DbusOperationsManager { - constructor(freeDesktopFileManager, gnomeNautilusPreview, gnomeArchiveManager) { - this.freeDesktopFileManager = freeDesktopFileManager; - this.gnomeNautilusPreviewManager = gnomeNautilusPreview; - this.gnomeArchiveManager = gnomeArchiveManager; - } - - _sendNoProxyError(callback) { - if (callback) { - GLib.idle_add(GLib.PRIORITY_LOW, () => { - callback(null, 'noProxy'); - return false; - }); - } - } - - ShowItemPropertiesRemote(selection, timestamp, callback = null) { - if (!this.freeDesktopFileManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.freeDesktopFileManager.proxy.ShowItemPropertiesRemote(selection, - this._getStartupId(selection, timestamp), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error showing properties: ${error.message}`); - } - } - ); - } - - ShowItemsRemote(showInFilesList, timestamp, callback = null) { - if (!this.freeDesktopFileManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.freeDesktopFileManager.proxy.ShowItemsRemote(showInFilesList, - this._getStartupId(showInFilesList, timestamp), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error showing file on desktop: ${error.message}`); - } - } - ); - } - - ShowFileRemote(uri, integer, boolean, callback = null) { - if (!this.gnomeNautilusPreviewManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.gnomeNautilusPreviewManager.proxy.ShowFileRemote(uri, integer, boolean, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error previewing file: ${error.message}`); - } - }); - } - - ExtractRemote(extractFileItem, folder, boolean, callback = null) { - if (!this.gnomeArchiveManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.gnomeArchiveManager.proxy.ExtractRemote(extractFileItem, folder, true, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error extracting files: ${error.message}`); - } - }); - } - - CompressRemote(compressFileItems, folder, boolean, callback = null) { - if (!this.gnomeArchiveManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.gnomeArchiveManager.proxy.CompressRemote(compressFileItems, folder, boolean, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error compressing files: ${error.message}`); - } - } - ); - } - - _getStartupId(fileUris, timestamp) { - if (!timestamp) { - return ''; - } - - const context = Gdk.Display.get_default().get_app_launch_context(); - context.set_timestamp(timestamp); - - if (!this._fileManager) { - this._fileManager = Gio.File.new_for_path('/').query_default_handler(null); - } - - return context.get_startup_notify_id(this._fileManager, - fileUris.map(uri => Gio.File.new_for_uri(uri))); - } -} - - -class RemoteFileOperationsManager extends DbusOperationsManager { - constructor(fileOperationsManager, freeDesktopFileManager, gnomeNautilusPreview, gnomeArchiveManager) { - super(freeDesktopFileManager, gnomeNautilusPreview, gnomeArchiveManager); - this.fileOperationsManager = fileOperationsManager; - this._createPlatformData(); - } - - _createPlatformData() { - this.platformData = this.fileOperationsManager.platformData = () => { - let parentWindow = Gtk.get_current_event()?.get_window(); - - let parentHandle = ''; - if (parentWindow) { - try { - imports.gi.versions.GdkX11 = '3.0'; - const {GdkX11} = imports.gi; - const topLevel = parentWindow.get_effective_toplevel(); - - if (topLevel.constructor.$gtype === GdkX11.X11Window.$gtype) { - const xid = GdkX11.X11Window.prototype.get_xid.call(topLevel); - parentHandle = `x11:${xid}`; - } /* else if (topLevel instanceof GdkWayland.Toplevel) { - FIXME: Need Gtk4 to use GdkWayland - const handle = GdkWayland.Toplevel.prototype.export_handle.call(topLevel); - parentHandle = `wayland:${handle}`; - } */ - } catch (e) { - logError(e, 'Impossible to determine the parent window'); - } - } - - return { - 'parent-handle': new GLib.Variant('s', parentHandle), - 'timestamp': new GLib.Variant('u', Gtk.get_current_event_time()), - 'window-position': new GLib.Variant('s', 'center'), - }; - }; - } - - MoveURIsRemote(fileList, uri, callback) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.MoveURIsRemote( - fileList, - uri, - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error moving files: ${error.message}`); - } - } - ); - } - - CopyURIsRemote(fileList, uri, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.CopyURIsRemote( - fileList, - uri, - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error copying files: ${error.message}`); - } - } - ); - } - - RenameURIRemote(fileList, uri, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.RenameURIRemote( - fileList, - uri, - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error copying files: ${error.message}`); - } - } - ); - } - - TrashURIsRemote(fileList, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.TrashURIsRemote( - fileList, - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error moving files: ${error.message}`); - } - } - ); - } - - DeleteURIsRemote(fileList, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.DeleteURIsRemote( - fileList, - this.platformData(), - (source, error) => { - if (callback) { - callback(source, error); - } - if (error) { - log(`Error deleting files on the desktop: ${error.message}`); - } - } - ); - } - - EmptyTrashRemote(askConfirmation, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.EmptyTrashRemote( - askConfirmation, - this.platformData(), - (source, error) => { - if (callback) { - callback(source, error); - } - if (error) { - log(`Error trashing files on the desktop: ${error.message}`); - } - } - ); - } - - UndoRemote(callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.UndoRemote( - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error performing undo: ${error.message}`); - } - } - ); - } - - RedoRemote(callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.RedoRemote( - this.platformData(), - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error performing redo: ${error.message}`); - } - } - ); - } - - UndoStatus() { - return this.fileOperationsManager.proxy.UndoStatus; - } -} - - -class LegacyRemoteFileOperationsManager extends DbusOperationsManager { - constructor(fileOperationsManager, freeDesktopFileManager, gnomeNautilusPreview, gnomeArchiveManager) { - super(freeDesktopFileManager, gnomeNautilusPreview, gnomeArchiveManager); - this.fileOperationsManager = fileOperationsManager; - } - - MoveURIsRemote(fileList, uri, callback) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.MoveURIsRemote( - fileList, - uri, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error moving files: ${error.message}`); - } - } - ); - } - - CopyURIsRemote(fileList, uri, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.CopyURIsRemote( - fileList, - uri, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error copying files: ${error.message}`); - } - } - ); - } - - RenameURIRemote(fileList, uri, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.RenameFileRemote( - fileList, - uri, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error renaming files: ${error.message}`); - } - } - ); - } - - TrashURIsRemote(fileList, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.TrashFilesRemote( - fileList, - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error moving files: ${error.message}`); - } - } - ); - } - - DeleteURIsRemote(fileList, callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.TrashFilesRemote( - fileList, - (source, error) => { - this.EmptyTrashRemote(); - if (callback) { - callback(source, error); - } - if (error) { - log(`Error deleting files on the desktop: ${error.message}`); - } - } - ); - } - - EmptyTrashRemote(callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.EmptyTrashRemote( - (source, error) => { - if (callback) { - callback(source, error); - } - if (error) { - log(`Error trashing files on the desktop: ${error.message}`); - } - } - ); - } - - UndoRemote(callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.UndoRemote( - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error performing undo: ${error.message}`); - } - } - ); - } - - RedoRemote(callback = null) { - if (!this.fileOperationsManager.proxy) { - this._sendNoProxyError(callback); - return; - } - this.fileOperationsManager.proxy.RedoRemote( - (result, error) => { - if (callback) { - callback(result, error); - } - if (error) { - log(`Error performing redo: ${error.message}`); - } - } - ); - } - - UndoStatus() { - return this.fileOperationsManager.proxy.UndoStatus; - } -} - - -/** - * - */ -function init() { - dbusManagerObject = new DBusManager(); - - let data = dbusManagerObject.getIntrospectionData( - 'org.gnome.Nautilus', - '/org/gnome/Nautilus/FileOperations2', - false); - - if (data) { - // NautilusFileOperations2 - NautilusFileOperations2 = new ProxyManager( - dbusManagerObject, - 'org.gnome.Nautilus', - '/org/gnome/Nautilus/FileOperations2', - 'org.gnome.Nautilus.FileOperations2', - false, - 'Nautilus' - ); - } else { - print('Emulating NautilusFileOperations2 with the old NautilusFileOperations interface'); - // Emulate NautilusFileOperations2 with the old interface - NautilusFileOperations2 = new ProxyManager( - dbusManagerObject, - 'org.gnome.Nautilus', - '/org/gnome/Nautilus', - 'org.gnome.Nautilus.FileOperations', - false, - 'Nautilus' - ); - } - - FreeDesktopFileManager = new ProxyManager( - dbusManagerObject, - 'org.freedesktop.FileManager1', - '/org/freedesktop/FileManager1', - 'org.freedesktop.FileManager1', - false, - 'Nautilus' - ); - - GnomeNautilusPreview = new ProxyManager( - dbusManagerObject, - 'org.gnome.NautilusPreviewer', - '/org/gnome/NautilusPreviewer', - 'org.gnome.NautilusPreviewer', - false, - 'Nautilus-Sushi' - ); - - GnomeArchiveManager = new ProxyManager( - dbusManagerObject, - 'org.gnome.ArchiveManager1', - '/org/gnome/ArchiveManager1', - 'org.gnome.ArchiveManager1', - false, - 'File-roller' - ); - - GtkVfsMetadata = new ProxyManager( - dbusManagerObject, - 'org.gtk.vfs.Metadata', - '/org/gtk/vfs/metadata', - 'org.gtk.vfs.Metadata', - false, - 'Gvfs daemon' - ); - - SwitcherooControl = new ProxyManager( - dbusManagerObject, - 'net.hadess.SwitcherooControl', - '/net/hadess/SwitcherooControl', - 'net.hadess.SwitcherooControl', - true, - 'Switcheroo control' - ); - discreteGpuAvailable = SwitcherooControl.isAvailable; - SwitcherooControl.connect('changed-status', (obj, newStatus) => { - discreteGpuAvailable = newStatus; - }); - - if (data) { - RemoteFileOperations = new RemoteFileOperationsManager(NautilusFileOperations2, FreeDesktopFileManager, GnomeNautilusPreview, GnomeArchiveManager); - } else { - RemoteFileOperations = new LegacyRemoteFileOperationsManager(NautilusFileOperations2, FreeDesktopFileManager, GnomeNautilusPreview, GnomeArchiveManager); - } - - extensionControl = Gio.DBusActionGroup.get( - Gio.DBus.session, - 'com.rastersoft.dingextension', - '/com/rastersoft/dingextension/control' - ); - - return dbusManagerObject; -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopGrid.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopGrid.js deleted file mode 100644 index 317e4b0..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopGrid.js +++ /dev/null @@ -1,587 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported DesktopGrid */ -'use strict'; -const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; - -const Prefs = imports.preferences; -const Enums = imports.enums; -const DesktopIconsUtil = imports.desktopIconsUtil; - -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - - -var elementSpacing = 2; - -var DesktopGrid = class { - _connectSignal(object, signal, callback) { - this._signalIds.push([object, object.connect(signal, callback)]); - } - - constructor(desktopManager, desktopName, desktopDescription, asDesktop, premultiplied) { - this._signalIds = []; - this._destroying = false; - this._desktopManager = desktopManager; - this._desktopName = desktopName; - this._asDesktop = asDesktop; - this._premultiplied = premultiplied; - this._asDesktop = asDesktop; - this._desktopDescription = desktopDescription; - this.updateWindowGeometry(); - this.updateUnscaledHeightWidthMargins(); - this.createGrids(); - - this._window = new Gtk.ApplicationWindow({application: desktopManager.mainApp, 'title': desktopName}); - this._windowContext = this._window.get_style_context(); - if (this._asDesktop) { - this._window.set_decorated(false); - this._window.set_deletable(false); - // For Wayland Transparent background, but only if this instance is working as desktop - this._windowContext.add_class('desktopwindow'); - // If we are under X11, Transparent background and everything else from here as well - if (this._desktopManager.using_X11) { - let screen = this._window.get_screen(); - let visual = screen.get_rgba_visual(); - if (visual && screen.is_composited()) { - this._window.set_visual(visual); - } else { - print('Unable to set Transparency under X11!'); - } - this._window.set_type_hint(Gdk.WindowTypeHint.DESKTOP); - this._window.stick(); - this._window.move(this._x / this._size_divisor, this._y / this._size_divisor); - } else { // Wayland - this._window.maximize(); - } - } else { - // Opaque black test window - this._windowContext.add_class('testwindow'); - } - this._window.set_resizable(false); - this._connectSignal(this._window, 'delete-event', () => { - if (this._destroying) { - return false; - } - if (this._asDesktop) { - // Do not destroy window when closing if the instance is working as desktop - return true; - } else { - // Exit if this instance is working as an stand-alone window - return false; - } - }); - - this._eventBox = new Gtk.EventBox({visible: true}); - this.sizeEventBox(); - this._window.add(this._eventBox); - this._container = new Gtk.Fixed(); - this._eventBox.add(this._container); - this.gridGlobalRectangle = new Gdk.Rectangle(); - this.setDropDestination(this._eventBox); - - this._selectedList = null; - this._connectSignal(this._container, 'draw', (widget, cr) => { - this._doDrawRubberBand(cr); - cr.$dispose(); - }); - - this.setGridStatus(); - - this._window.show_all(); - this._window.set_size_request(this._windowWidth, this._windowHeight); - this._window.resize(this._windowWidth, this._windowHeight); - - this._eventBox.add_events(Gdk.EventMask.BUTTON_MOTION_MASK | - Gdk.EventMask.BUTTON_PRESS_MASK | - Gdk.EventMask.BUTTON_RELEASE_MASK | - Gdk.EventMask.KEY_RELEASE_MASK); - this._connectSignal(this._eventBox, 'button-press-event', (actor, event) => { - let [a, x, y] = event.get_coords(); - [x, y] = this.coordinatesLocalToGlobal(x, y); - this._desktopManager.onPressButton(x, y, event, this); - return false; - }); - this._connectSignal(this._eventBox, 'motion-notify-event', (actor, event) => { - let [a, x, y] = event.get_coords(); - [x, y] = this.coordinatesLocalToGlobal(x, y); - this._desktopManager.onMotion(x, y); - }); - this._connectSignal(this._eventBox, 'button-release-event', (actor, event) => { - this._desktopManager.onReleaseButton(this); - }); - - this._connectSignal(this._window, 'key-press-event', (actor, event) => { - this._desktopManager.onKeyPress(event, this); - }); - this.updateGridRectangle(); - } - - updateGridDescription(desktopDescription) { - this._desktopDescription = desktopDescription; - } - - updateWindowGeometry() { - this._zoom = this._desktopDescription.zoom; - this._x = this._desktopDescription.x; - this._y = this._desktopDescription.y; - this._monitor = this._desktopDescription.monitorIndex; - this._size_divisor = this._zoom; - if (this._asDesktop) { - if (this._desktopManager.using_X11) { - this._size_divisor = Math.ceil(this._zoom); - } else if (this._premultiplied) { - this._size_divisor = 1; - } - } - this._windowWidth = Math.floor(this._desktopDescription.width / this._size_divisor); - this._windowHeight = Math.floor(this._desktopDescription.height / this._size_divisor); - } - - resizeWindow() { - this.updateWindowGeometry(); - this._desktopName = `@!${this._x},${this._y};BDHF`; - if (this._desktopManager.using_X11) { - this._window.move(this._x / this._size_divisor, this._y / this._size_divisor); - } - this._window.set_title(this._desktopName); - this._window.set_size_request(this._windowWidth, this._windowHeight); - this._window.resize(this._windowWidth, this._windowHeight); - } - - updateUnscaledHeightWidthMargins() { - this._marginTop = this._desktopDescription.marginTop; - this._marginBottom = this._desktopDescription.marginBottom; - this._marginLeft = this._desktopDescription.marginLeft; - this._marginRight = this._desktopDescription.marginRight; - this._width = this._desktopDescription.width - this._marginLeft - this._marginRight; - this._height = this._desktopDescription.height - this._marginTop - this._marginBottom; - } - - createGrids() { - this._width = Math.floor(this._width / this._size_divisor); - this._height = Math.floor(this._height / this._size_divisor); - this._marginTop = Math.floor(this._marginTop / this._size_divisor); - this._marginBottom = Math.floor(this._marginBottom / this._size_divisor); - this._marginLeft = Math.floor(this._marginLeft / this._size_divisor); - this._marginRight = Math.floor(this._marginRight / this._size_divisor); - this._maxColumns = Math.floor(this._width / (Prefs.get_desired_width() + 4 * elementSpacing)); - this._maxRows = Math.floor(this._height / (Prefs.get_desired_height() + 4 * elementSpacing)); - this._elementWidth = Math.floor(this._width / this._maxColumns); - this._elementHeight = Math.floor(this._height / this._maxRows); - } - - updateGridRectangle() { - this.gridGlobalRectangle.x = this._x + this._marginLeft; - this.gridGlobalRectangle.y = this._y + this._marginTop; - this.gridGlobalRectangle.width = this._width; - this.gridGlobalRectangle.height = this._height; - } - - sizeEventBox() { - this._eventBox.margin_top = this._marginTop; - this._eventBox.margin_bottom = this._marginBottom; - this._eventBox.margin_start = this._marginLeft; - this._eventBox.margin_end = this._marginRight; - } - - setGridStatus() { - this._fileItems = {}; - this._gridStatus = {}; - for (let y = 0; y < this._maxRows; y++) { - for (let x = 0; x < this._maxColumns; x++) { - this._setGridUse(x, y, false); - } - } - } - - resizeGrid() { - this.updateUnscaledHeightWidthMargins(); - this.createGrids(); - this.updateGridRectangle(); - this.sizeEventBox(); - this.setGridStatus(); - } - - destroy() { - this._destroying = true; - /* Disconnect signals */ - for (let [object, signalId] of this._signalIds) { - object.disconnect(signalId); - } - this._signalIds = []; - this._window.destroy(); - } - - setDropDestination(dropDestination) { - dropDestination.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP, null, Gdk.DragAction.MOVE | Gdk.DragAction.COPY | Gdk.DragAction.DEFAULT); - let targets = new Gtk.TargetList(null); - targets.add(Gdk.atom_intern('x-special/ding-icon-list', false), Gtk.TargetFlags.SAME_APP, - Enums.DndTargetInfo.DING_ICON_LIST); - targets.add(Gdk.atom_intern('x-special/gnome-icon-list', false), 0, - Enums.DndTargetInfo.GNOME_ICON_LIST); - targets.add(Gdk.atom_intern('text/uri-list', false), 0, - Enums.DndTargetInfo.URI_LIST); - targets.add(Gdk.atom_intern('text/plain', false), 0, - Enums.DndTargetInfo.TEXT_PLAIN); - dropDestination.drag_dest_set_target_list(targets); - targets = undefined; // to avoid memory leaks - this._connectSignal(dropDestination, 'drag-motion', (widget, context, x, y, time) => { - this.receiveMotion(x, y); - - if (DesktopIconsUtil.getModifiersInDnD(context, Gdk.ModifierType.CONTROL_MASK)) { - Gdk.drag_status(context, Gdk.DragAction.COPY, time); - } else { - Gdk.drag_status(context, Gdk.DragAction.MOVE, time); - } - }); - this._connectSignal(this._eventBox, 'drag-leave', (widget, context, time) => { - this.receiveLeave(); - }); - this._connectSignal(dropDestination, 'drag-data-received', (widget, context, x, y, selection, info, time) => { - const forceCopy = context.get_selected_action() === Gdk.DragAction.COPY; - this.receiveDrop(context, x, y, selection, info, false, forceCopy); - }); - } - - receiveLeave() { - this._desktopManager.onDragLeave(); - } - - receiveMotion(x, y, global) { - if (!global) { - x = this._elementWidth * Math.floor(x / this._elementWidth); - y = this._elementHeight * Math.floor(y / this._elementHeight); - [x, y] = this.coordinatesLocalToGlobal(x, y); - } - this._desktopManager.onDragMotion(x, y); - } - - receiveDrop(context, x, y, selection, info, forceLocal, forceCopy) { - if (!forceLocal) { - x = this._elementWidth * Math.floor(x / this._elementWidth); - y = this._elementHeight * Math.floor(y / this._elementHeight); - [x, y] = this.coordinatesLocalToGlobal(x, y); - } - this._desktopManager.onDragDataReceived(context, x, y, selection, info, forceLocal, forceCopy); - this._window.queue_draw(); - } - - highLightGridAt(x, y) { - let selected = this.getGridAt(x, y, false); - this._selectedList = [selected]; - this._window.queue_draw(); - } - - unHighLightGrids() { - this._selectedList = null; - this._window.queue_draw(); - } - - _getGridCoordinates(x, y) { - let placeX = Math.floor(x / this._elementWidth); - let placeY = Math.floor(y / this._elementHeight); - placeX = DesktopIconsUtil.clamp(placeX, 0, this._maxColumns - 1); - placeY = DesktopIconsUtil.clamp(placeY, 0, this._maxRows - 1); - return [placeX, placeY]; - } - - gridInUse(x, y) { - let [placeX, placeY] = this._getGridCoordinates(x, y); - return !this._isEmptyAt(placeX, placeY); - } - - getGridLocalCoordinates(x, y) { - let [column, row] = this._getGridCoordinates(x, y); - let localX = Math.floor(this._width * column / this._maxColumns); - let localY = Math.floor(this._height * row / this._maxRows); - return [localX, localY]; - } - - _fileAt(x, y) { - let [placeX, placeY] = this._getGridCoordinates(x, y); - return this._gridStatus[placeY * this._maxColumns + placeX]; - } - - refreshDrag(selectedList, ox, oy) { - if (selectedList === null) { - this._selectedList = null; - this._window.queue_draw(); - return; - } - let newSelectedList = []; - for (let [x, y] of selectedList) { - x += this._elementWidth / 2; - y += this._elementHeight / 2; - x += ox; - y += oy; - let r = this.getGridAt(x, y); - if (r && !isNaN(r[0]) && !isNaN(r[1]) && (!this.gridInUse(r[0], r[1]) || this._fileAt(r[0], r[1]).isSelected)) { - newSelectedList.push(r); - } - } - if (newSelectedList.length == 0) { - if (this._selectedList !== null) { - this._selectedList = null; - this._window.queue_draw(); - } - return; - } - if (this._selectedList !== null) { - if ((newSelectedList[0][0] == this._selectedList[0][0]) && (newSelectedList[0][1] == this._selectedList[0][1])) { - return; - } - } - this._selectedList = newSelectedList; - this._window.queue_draw(); - } - - queue_draw() { - this._window.queue_draw(); - } - - _doDrawRubberBand(cr) { - if (this._desktopManager.rubberBand && this._desktopManager.selectionRectangle) { - if (!this.gridGlobalRectangle.intersect(this._desktopManager.selectionRectangle)[0]) { - return; - } - let [xInit, yInit] = this.coordinatesGlobalToLocal(this._desktopManager.x1, this._desktopManager.y1); - let [xFin, yFin] = this.coordinatesGlobalToLocal(this._desktopManager.x2, this._desktopManager.y2); - - cr.rectangle(xInit + 0.5, yInit + 0.5, xFin - xInit, yFin - yInit); - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ - red: this._desktopManager.selectColor.red, - green: this._desktopManager.selectColor.green, - blue: this._desktopManager.selectColor.blue, - alpha: 0.6, - }) - ); - cr.fill(); - cr.setLineWidth(1); - cr.rectangle(xInit + 0.5, yInit + 0.5, xFin - xInit, yFin - yInit); - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ - red: this._desktopManager.selectColor.red, - green: this._desktopManager.selectColor.green, - blue: this._desktopManager.selectColor.blue, - alpha: 1.0, - }) - ); - cr.stroke(); - } - if (this._desktopManager.showDropPlace && (this._selectedList !== null)) { - for (let [x, y] of this._selectedList) { - cr.rectangle(x + 0.5, y + 0.5, this._elementWidth, this._elementHeight); - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ - red: 1.0 - this._desktopManager.selectColor.red, - green: 1.0 - this._desktopManager.selectColor.green, - blue: 1.0 - this._desktopManager.selectColor.blue, - alpha: 0.4, - }) - ); - cr.fill(); - cr.setLineWidth(0.5); - cr.rectangle(x + 0.5, y + 0.5, this._elementWidth, this._elementHeight); - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ - red: 1.0 - this._desktopManager.selectColor.red, - green: 1.0 - this._desktopManager.selectColor.green, - blue: 1.0 - this._desktopManager.selectColor.blue, - alpha: 1.0, - }) - ); - cr.stroke(); - } - } - } - - getDistance(x, y) { - /** - * Checks if these coordinates belong to this grid. - * - * @returns -1 if there is no free space for new icons; - * 0 if the coordinates are inside this grid; - * or the distance to the middle point, if none of the previous - */ - - let isFree = false; - for (let element in this._gridStatus) { - if (!this._gridStatus[element]) { - isFree = true; - break; - } - } - if (!isFree) { - return -1; - } - if (this._coordinatesBelongToThisGrid(x, y)) { - return 0; - } - return Math.pow(x - (this._x + this._windowWidth * this._zoom / 2), 2) + Math.pow(x - (this._y + this._windowHeight * this._zoom / 2), 2); - } - - coordinatesGlobalToLocal(X, Y, widget = null) { - X -= this._x; - Y -= this._y; - if (!widget) { - widget = this._eventBox; - } - let [belong, x, y] = this._window.translate_coordinates(widget, X, Y); - return [x, y]; - } - - coordinatesLocalToGlobal(x, y, widget = null) { - if (!widget) { - widget = this._eventBox; - } - let [belongs, X, Y] = widget.translate_coordinates(this._window, x, y); - return [X + this._x, Y + this._y]; - } - - _addFileItemTo(fileItem, column, row, coordinatesAction) { - if (this._destroying) { - return; - } - let localX = Math.floor(this._width * column / this._maxColumns); - let localY = Math.floor(this._height * row / this._maxRows); - this._container.put(fileItem.container, localX + elementSpacing, localY + elementSpacing); - this._setGridUse(column, row, fileItem); - this._fileItems[fileItem.uri] = [column, row, fileItem]; - let [x, y] = this.coordinatesLocalToGlobal(localX + elementSpacing, localY + elementSpacing); - fileItem.setCoordinates(x, - y, - this._elementWidth - 2 * elementSpacing, - this._elementHeight - 2 * elementSpacing, - elementSpacing, - this); - /* If this file is new in the Desktop and hasn't yet - * fixed coordinates, store the new possition to ensure - * that the next time it will be shown in the same possition. - * Also store the new possition if it has been moved by the user, - * and not triggered by a screen change. - */ - if ((fileItem.savedCoordinates == null) || (coordinatesAction == Enums.StoredCoordinates.OVERWRITE)) { - fileItem.savedCoordinates = [x, y]; - } - } - - removeItem(fileItem) { - if (fileItem.uri in this._fileItems) { - let [column, row, tmp] = this._fileItems[fileItem.uri]; - this._setGridUse(column, row, false); - this._container.remove(fileItem.container); - delete this._fileItems[fileItem.uri]; - } - } - - addFileItemCloseTo(fileItem, x, y, coordinatesAction) { - let addVolumesOpposite = Prefs.desktopSettings.get_boolean('add-volumes-opposite'); - let [column, row] = this._getEmptyPlaceClosestTo(x, - y, - coordinatesAction, - fileItem.isDrive && addVolumesOpposite); - this._addFileItemTo(fileItem, column, row, coordinatesAction); - } - - _isEmptyAt(x, y) { - return this._gridStatus[y * this._maxColumns + x] === false; - } - - _setGridUse(x, y, inUse) { - this._gridStatus[y * this._maxColumns + x] = inUse; - } - - getGridAt(x, y, globalCoordinates = false) { - if (this._coordinatesBelongToThisGrid(x, y)) { - [x, y] = this.coordinatesGlobalToLocal(x, y); - if (globalCoordinates) { - x = this._elementWidth * Math.floor((x / this._elementWidth) + 0.5); - y = this._elementHeight * Math.floor((y / this._elementHeight) + 0.5); - [x, y] = this.coordinatesLocalToGlobal(x, y); - return [x, y]; - } else { - return this.getGridLocalCoordinates(x, y); - } - } else { - return null; - } - } - - _coordinatesBelongToThisGrid(X, Y) { - let checkRectangle = new Gdk.Rectangle({x: X, y: Y, width: 1, height: 1}); - return this.gridGlobalRectangle.intersect(checkRectangle)[0]; - } - - _getEmptyPlaceClosestTo(x, y, coordinatesAction, reverseHorizontal) { - [x, y] = this.coordinatesGlobalToLocal(x, y); - let placeX = Math.floor(x / this._elementWidth); - let placeY = Math.floor(y / this._elementHeight); - - let cornerInversion = Prefs.get_start_corner(); - if (reverseHorizontal) { - cornerInversion[0] = !cornerInversion[0]; - } - - placeX = DesktopIconsUtil.clamp(placeX, 0, this._maxColumns - 1); - placeY = DesktopIconsUtil.clamp(placeY, 0, this._maxRows - 1); - if (this._isEmptyAt(placeX, placeY) && (coordinatesAction != Enums.StoredCoordinates.ASSIGN)) { - return [placeX, placeY]; - } - let found = false; - let resColumn = null; - let resRow = null; - let minDistance = Infinity; - let column, row; - for (let tmpColumn = 0; tmpColumn < this._maxColumns; tmpColumn++) { - if (cornerInversion[0]) { - column = this._maxColumns - tmpColumn - 1; - } else { - column = tmpColumn; - } - for (let tmpRow = 0; tmpRow < this._maxRows; tmpRow++) { - if (cornerInversion[1]) { - row = this._maxRows - tmpRow - 1; - } else { - row = tmpRow; - } - if (!this._isEmptyAt(column, row)) { - continue; - } - - let proposedX = column * this._elementWidth; - let proposedY = row * this._elementHeight; - if (coordinatesAction == Enums.StoredCoordinates.ASSIGN) { - return [column, row]; - } - let distance = DesktopIconsUtil.distanceBetweenPoints(proposedX, proposedY, x, y); - if (distance < minDistance) { - found = true; - minDistance = distance; - resColumn = column; - resRow = row; - } - } - } - - if (!found) { - throw new Error('Not enough place at monitor'); - } - - return [resColumn, resRow]; - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconItem.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconItem.js deleted file mode 100644 index c116ed3..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconItem.js +++ /dev/null @@ -1,787 +0,0 @@ - -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2021 Sundeep Mediratta (smedius@gmail.com) - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * SwitcherooControl code based on code original from Marsch84 - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported dropDestination */ -'use strict'; -const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; -const Pango = imports.gi.Pango; -const GdkPixbuf = imports.gi.GdkPixbuf; -const Cairo = imports.gi.cairo; -const DesktopIconsUtil = imports.desktopIconsUtil; - -const Prefs = imports.preferences; -const Enums = imports.enums; - -const ByteArray = imports.byteArray; -const Signals = imports.signals; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var desktopIconItem = class desktopIconItem { - constructor(desktopManager, fileExtra) { - this._signalIds = []; - this._desktopManager = desktopManager; - this._fileExtra = fileExtra; - this._loadThumbnailDataCancellable = null; - this._queryFileInfoCancellable = null; - this._grid = null; - this._lastClickTime = 0; - this._lastClickButton = 0; - this._clickCount = 0; - this._isSelected = false; - this._isSpecial = false; - this._primaryButtonPressed = false; - this._savedCoordinates = null; - this._dropCoordinates = null; - this._destroyed = false; - } - - /** ********************* - * Destroyers * - ***********************/ - - removeFromGrid(callOnDestroy) { - if (this._grid) { - this._grid.removeItem(this); - this._grid = null; - } - if (callOnDestroy) { - this._onDestroy(); - } - } - - _destroy() { - /* Regular file data */ - if (this._queryFileInfoCancellable) { - this._queryFileInfoCancellable.cancel(); - } - - /* Thumbnailing */ - if (this._loadThumbnailDataCancellable) { - this._loadThumbnailDataCancellable.cancel(); - } - /* Disconnect signals */ - for (let [object, signalId] of this._signalIds) { - object.disconnect(signalId); - } - this._signalIds = []; - this.container.destroy(); - this.container = null; - this._eventBox = null; - this._shieldEventBox = null; - this._labelEventBox = null; - this._shieldLabelEventBox = null; - this._icon = null; - this._iconContainer = null; - this._label = null; - this._labelContainer = null; - this.iconRectangle = null; - } - - _onDestroy() { - if (!this._destroyed) { - this._destroy(); - this._destroyed = true; - } - } - - _connectSignal(object, signal, callback) { - this._signalIds.push([object, object.connect(signal, callback)]); - } - - /** ********************* - * Creators * - ***********************/ - - _createIconActor() { - this.container = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, halign: Gtk.Align.CENTER}); - this._connectSignal(this.container, 'destroy', () => this._onDestroy()); - this._eventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); - this._shieldEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); - this._labelEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); - this._shieldLabelEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); - - this._icon = new Gtk.Image(); - this._iconContainer = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL}); - this._iconContainer.pack_start(this._icon, true, true, 0); - this._iconContainer.set_baseline_position(Gtk.BaselinePosition.CENTER); - this._eventBox.add(this._iconContainer); - this._shieldEventBox.add(this._eventBox); - - this._label = new Gtk.Label(); - this._labelContainer = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, halign: Gtk.Align.CENTER}); - let labelStyleContext = this._label.get_style_context(); - if (this._desktopManager.darkText) { - labelStyleContext.add_class('file-label-dark'); - } else { - labelStyleContext.add_class('file-label'); - } - labelStyleContext = undefined; // prevent memory leaks - this._label.set_ellipsize(Pango.EllipsizeMode.END); - this._label.set_line_wrap(true); - this._label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR); - this._label.set_yalign(0.0); - this._label.set_justify(Gtk.Justification.CENTER); - this._label.set_lines(2); - this._labelContainer.pack_start(this._label, false, true, 0); - this._labelEventBox.add(this._labelContainer); - this._shieldLabelEventBox.add(this._labelEventBox); - - this.container.pack_start(this._shieldEventBox, false, false, 0); - this.container.pack_start(this._shieldLabelEventBox, false, false, 0); - - this._styleContext = this._iconContainer.get_style_context(); - this._labelStyleContext = this._labelContainer.get_style_context(); - this._styleContext.add_class('file-item'); - this._labelStyleContext.add_class('file-item'); - - this.iconRectangle = new Gdk.Rectangle(); - this.labelRectangle = new Gdk.Rectangle(); - - /* We need to allow the "button-press" event to pass through the callbacks, to allow the DnD to work - * But we must avoid them to reach the main window. - * The solution is to allow them to pass in a EventBox, used both for detecting the events and the DnD, and block them - * in a second EventBox, located outside. - */ - this._connectSignal(this._shieldEventBox, 'button-press-event', (actor, event) => { - return true; - }); - this._connectSignal(this._shieldLabelEventBox, 'button-press-event', (actor, event) => { - return true; - }); - this._connectSignal(this._eventBox, 'button-press-event', (actor, event) => this._onPressButton(actor, event)); - this._connectSignal(this._eventBox, 'enter-notify-event', (actor, event) => this._onEnter(this._eventBox)); - this._connectSignal(this._eventBox, 'leave-notify-event', (actor, event) => this._onLeave(this._eventBox)); - this._connectSignal(this._eventBox, 'button-release-event', (actor, event) => this._onReleaseButton(actor, event)); - this._connectSignal(this._eventBox, 'drag-motion', (widget, context, x, y, time) => { - this.highLightDropTarget(x, y); - this._updateDragStatus(context, time); - }); - this._connectSignal(this._eventBox, 'drag-leave', () => { - this.unHighLightDropTarget(); - }); - this._connectSignal(this._eventBox, 'size-allocate', () => this._calculateIconRectangle()); - this._connectSignal(this._labelEventBox, 'button-press-event', (actor, event) => this._onPressButton(actor, event)); - this._connectSignal(this._labelEventBox, 'enter-notify-event', (actor, event) => this._onEnter(this._labelEventBox)); - this._connectSignal(this._labelEventBox, 'leave-notify-event', (actor, event) => this._onLeave(this._labelEventBox)); - this._connectSignal(this._labelEventBox, 'button-release-event', (actor, event) => this._onReleaseButton(actor, event)); - this._connectSignal(this._labelEventBox, 'drag-motion', (widget, context, x, y, time) => { - this.highLightDropTarget(x, y); - this._updateDragStatus(context, time); - }); - this._connectSignal(this._labelEventBox, 'drag-leave', () => { - this.unHighLightDropTarget(); - }); - this._connectSignal(this._labelEventBox, 'size-allocate', () => { - this._doLabelSizeAllocated(); - }); - this._connectSignal(this.container, 'drag-motion', (widget, context, x, y, time) => { - this.highLightDropTarget(x, y); - this._updateDragStatus(context, time); - }); - this._connectSignal(this.container, 'drag-leave', () => { - this.unHighLightDropTarget(); - }); - - if (this._desktopManager.showDropPlace) { - this._setDropDestination(this.container); - } else { - this._setDropDestination(this._eventBox); - this._setDropDestination(this._labelEventBox); - } - this._setDragSource(this._eventBox); - this._setDragSource(this._labelEventBox); - this.container.show_all(); - } - - _doLabelSizeAllocated() { - this._calculateLabelRectangle(); - } - - _calculateIconRectangle() { - this.iconwidth = this._iconContainer.get_allocated_width(); - this.iconheight = this._iconContainer.get_allocated_height(); - let [x, y] = this._grid.coordinatesLocalToGlobal(0, 0, this._iconContainer); - this.iconRectangle.x = x; - this.iconRectangle.y = y; - this.iconRectangle.width = this.iconwidth; - this.iconRectangle.height = this.iconheight; - } - - _calculateLabelRectangle() { - this.labelwidth = this._labelContainer.get_allocated_width(); - this.labelheight = this._labelContainer.get_allocated_height(); - let [x, y] = this._grid.coordinatesLocalToGlobal(0, 0, this._labelContainer); - this.labelRectangle.x = x; - this.labelRectangle.y = y; - this.labelRectangle.width = this.labelwidth; - this.labelRectangle.height = this.labelheight; - } - - setCoordinates(x, y, width, height, margin, grid) { - this._x1 = x; - this._y1 = y; - this.width = width; - this.height = height; - this._grid = grid; - this.container.set_size_request(width, height); - this._label.margin_start = margin; - this._label.margin_end = margin; - this._label.margin_bottom = margin; - this._iconContainer.margin_top = margin; - this._calculateIconRectangle(); - this._calculateLabelRectangle(); - } - - getCoordinates() { - this._x2 = this._x1 + this.container.get_allocated_width() - 1; - this._y2 = this._y1 + this.container.get_allocated_height() - 1; - return [this._x1, this._y1, this._x2, this._y2, this._grid]; - } - - _setLabelName(text) { - this._currentFileName = text; - this._eventBox.set_tooltip_text(text); - let lastCutPos = -1; - let newText = ''; - for (let pos = 0; pos < text.length; pos++) { - let character = text[pos]; - newText += character; - if (pos < (text.length - 1)) { - var nextChar = text[pos + 1]; - } else { - var nextChar = ''; - } - if (character == ' ') { - lastCutPos = pos; - } - if (['.', ',', '-', '_', '@', ':'].includes(character)) { - /* if the next character is already an space or this is the last - * character, the string will be naturally cut here, so we do - * nothing. - */ - if ((nextChar == ' ') || (nextChar == '')) { - continue; - } - /* if there is a cut element in the last four previous characters, - * do not add a new cut element. - */ - if ((lastCutPos > -1) && ((pos - lastCutPos) < 4)) { - continue; - } - newText += '\u200B'; - } - } - this._label.label = newText; - } - - /** ********************* - * Button Clicks * - ***********************/ - - _updateClickState(event) { - let settings = Gtk.Settings.get_default(); - - if ((event.get_button()[1] == this._lastClickButton) && - ((event.get_time() - this._lastClickTime) < settings.gtk_double_click_time)) { - this._clickCount++; - } else { - this._clickCount = 1; - } - - this._lastClickTime = event.get_time(); - this._lastClickButton = event.get_button()[1]; - } - - getClickCount() { - return this._clickCount; - } - - _onPressButton(actor, event) { - this._updateClickState(event); - let button = event.get_button()[1]; - let [a, x, y] = event.get_coords(); - let state = event.get_state()[1]; - this._buttonPressInitialX = x; - this._buttonPressInitialY = y; - let shiftPressed = !!(state & Gdk.ModifierType.SHIFT_MASK); - let controlPressed = !!(state & Gdk.ModifierType.CONTROL_MASK); - if (button == 3) { - this._doButtonThreePressed(event, shiftPressed, controlPressed); - } else if (button == 1) { - this._doButtonOnePressed(event, shiftPressed, controlPressed); - } - return false; - } - - _onReleaseButton(actor, event) { - let button = event.get_button()[1]; - if (button == 1) { - this._doButtonOneReleased(event); - } - return false; - } - - _doButtonThreePressed(event) { - if (!this._isSelected) { - this._desktopManager.selected(this, Enums.Selection.RIGHT_BUTTON); - } - this._desktopManager.fileItemMenu.showMenu(this, event); - } - - _doButtonOnePressed(event, shiftPressed, controlPressed) { - if (this.getClickCount() == 1) { - this._primaryButtonPressed = true; - if (shiftPressed || controlPressed) { - this._desktopManager.selected(this, Enums.Selection.WITH_SHIFT); - } else { - this._desktopManager.selected(this, Enums.Selection.ALONE); - } - } - } - - _doButtonOneReleased(event) { - } - - /** ********************* - * Drag and Drop * - ***********************/ - - _onEnter(element) { - if (!this._styleContext.has_class('file-item-hover')) { - this._styleContext.add_class('file-item-hover'); - this._labelStyleContext.add_class('file-item-hover'); - } - if (Prefs.CLICK_POLICY_SINGLE) { - let window = element.get_window(); - if (window) { - window.set_cursor(Gdk.Cursor.new_from_name(Gdk.Display.get_default(), 'hand')); - } - } - return false; - } - - _onLeave(element) { - this._primaryButtonPressed = false; - if (this._styleContext.has_class('file-item-hover')) { - this._styleContext.remove_class('file-item-hover'); - this._labelStyleContext.remove_class('file-item-hover'); - } - if (Prefs.CLICK_POLICY_SINGLE) { - let window = element.get_window(); - if (window) { - window.set_cursor(Gdk.Cursor.new_from_name(Gdk.Display.get_default(), 'default')); - } - } - return false; - } - - _hasToRouteDragToGrid() { - if (this._grid) { - return true; - } - return false; - } - - _updateDragStatus(context, time) { - if (DesktopIconsUtil.getModifiersInDnD(context, Gdk.ModifierType.CONTROL_MASK)) { - Gdk.drag_status(context, Gdk.DragAction.COPY, time); - } else { - Gdk.drag_status(context, Gdk.DragAction.MOVE, time); - } - } - - highLightDropTarget() { - if (this._hasToRouteDragToGrid()) { - this._grid.receiveMotion(this._x1, this._y1, true); - return; - } - if (!this._styleContext.has_class('desktop-icons-selected')) { - this._styleContext.add_class('desktop-icons-selected'); - this._labelStyleContext.add_class('desktop-icons-selected'); - } - this._grid.highLightGridAt(this._x1, this._y1); - } - - unHighLightDropTarget() { - if (this._hasToRouteDragToGrid()) { - this._grid.receiveLeave(); - return; - } - if (!this._isSelected && this._styleContext.has_class('desktop-icons-selected')) { - this._styleContext.remove_class('desktop-icons-selected'); - this._labelStyleContext.remove_class('desktop-icons-selected'); - } - this._grid.unHighLightGrids(); - } - - setSelected() { - this._isSelected = true; - this._setSelectedStatus(); - } - - unsetSelected() { - this._isSelected = false; - this._setSelectedStatus(); - } - - toggleSelected() { - this._isSelected = !this._isSelected; - this._setSelectedStatus(); - } - - _setSelectedStatus() { - if (this._isSelected && !this._styleContext.has_class('desktop-icons-selected')) { - this._styleContext.add_class('desktop-icons-selected'); - this._labelStyleContext.add_class('desktop-icons-selected'); - } - if (!this._isSelected && this._styleContext.has_class('desktop-icons-selected')) { - this._styleContext.remove_class('desktop-icons-selected'); - this._labelStyleContext.remove_class('desktop-icons-selected'); - } - } - - _setDragSource(widget) { - widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, null, Gdk.DragAction.MOVE | Gdk.DragAction.COPY); - let targets = new Gtk.TargetList(null); - targets.add(Gdk.atom_intern('x-special/ding-icon-list', false), - Gtk.TargetFlags.SAME_APP, Enums.DndTargetInfo.DING_ICON_LIST); - if ((this._fileExtra != Enums.FileType.USER_DIRECTORY_TRASH) && - (this._fileExtra != Enums.FileType.USER_DIRECTORY_HOME) && - (this._fileExtra != Enums.FileType.EXTERNAL_DRIVE)) { - targets.add(Gdk.atom_intern('x-special/gnome-icon-list', false), 0, - Enums.DndTargetInfo.GNOME_ICON_LIST); - targets.add(Gdk.atom_intern('text/uri-list', false), 0, - Enums.DndTargetInfo.URI_LIST); - } - widget.drag_source_set_target_list(targets); - targets = undefined; // prevent memory leaks - this._connectSignal(widget, 'drag-begin', (w, context) => { - const scale = this._icon.get_scale_factor(); - let surf = new Cairo.ImageSurface(Cairo.SurfaceType.IMAGE, this.container.get_allocated_width() * scale, this.container.get_allocated_height() * scale); - // setDeviceScale was introduced to GJS in version 1.69.2 - if (scale != 1.0 && surf.setDeviceScale !== undefined) { - surf.setDeviceScale(scale, scale); - } - let cr = new Cairo.Context(surf); - this.container.draw(cr); - let itemnumber = this._desktopManager.getNumberOfSelectedItems(); - if (itemnumber > 1) { - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ - red: this._desktopManager.selectColor.red, - green: this._desktopManager.selectColor.green, - blue: this._desktopManager.selectColor.blue, - alpha: 0.6, - }) - ); - itemnumber -= 1; - switch (itemnumber.toString().length) { - case 1: - cr.rectangle(1, 1, 30, 20); - break; - case 2: - cr.rectangle(1, 1, 40, 20); - break; - default: - cr.rectangle(1, 1, 50, 20); - break; - } - cr.fill(); - cr.setFontSize(18); - Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({red: 1.0, green: 1.0, blue: 1.0, alpha: 1})); - cr.moveTo(1, 17); - cr.showText(`+${itemnumber}`); - } - Gtk.drag_set_icon_surface(context, surf); - let [x, y] = this._calculateOffset(widget); - context.set_hotspot(x, y); - this._desktopManager.onDragBegin(this); - cr.$dispose(); - }); - this._connectSignal(widget, 'drag-data-get', (w, context, data, info, time) => { - let dragData = this._desktopManager.fillDragDataGet(info); - if (dragData != null) { - let list = ByteArray.fromString(dragData[1]); - data.set(dragData[0], 8, list); - } - }); - this._connectSignal(widget, 'drag-end', (w, context) => { - this._desktopManager.onDragEnd(); - }); - } - - _calculateOffset(widget) { - if (widget == this._eventBox) { - return [((this.width - this.iconwidth) / 2) + this._buttonPressInitialX, this._buttonPressInitialY]; - } else { - return [((this.width - this.labelwidth) / 2) + this._buttonPressInitialX, (this.iconheight + 2) + this._buttonPressInitialY]; - } - } - - _setDropDestination(dropDestination) { - - } - - /** ********************* - * Icon Rendering * - ***********************/ - - updateIcon() { - this._updateIcon(); - } - - async _updateIcon() { - if (this._destroyed) { - return; - } - - this._icon.set_padding(0, 0); - try { - let customIcon = this._fileInfo.get_attribute_as_string('metadata::custom-icon'); - if (customIcon && (customIcon != '')) { - let customIconFile = Gio.File.new_for_uri(customIcon); - if (customIconFile.query_exists(null)) { - let loadedImage = await this._loadImageAsIcon(customIconFile); - if (loadedImage | this._destroyed) { - return; - } - } - } - } catch (error) { - print(`Error while updating icon: ${error.message}.\n${error.stack}`); - } - - if (this._fileExtra == Enums.FileType.USER_DIRECTORY_TRASH) { - let pixbuf = this._createEmblemedIcon(this._fileInfo.get_icon(), null); - const scale = this._icon.get_scale_factor(); - let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); - this._icon.set_from_surface(surface); - return; - } - let iconSet = false; - if (Prefs.nautilusSettings.get_string('show-image-thumbnails') != 'never') { - let thumbnail = this._desktopManager.thumbnailLoader.getThumbnail(this, this._updateIcon.bind(this)); - if (thumbnail != null) { - let thumbnailFile = Gio.File.new_for_path(thumbnail); - iconSet = await this._loadImageAsIcon(thumbnailFile); - if (this._destroyed) { - return; - } - } - } - - if (!iconSet) { - let pixbuf; - if (this._isBrokenSymlink) { - pixbuf = this._createEmblemedIcon(null, 'text-x-generic'); - } else if (this._desktopFile && this._desktopFile.has_key('Icon')) { - pixbuf = this._createEmblemedIcon(null, this._desktopFile.get_string('Icon')); - } else { - pixbuf = this._createEmblemedIcon(this._getDefaultIcon(), null); - } - const scale = this._icon.get_scale_factor(); - let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); - this._icon.set_from_surface(surface); - } - } - - _getDefaultIcon() { - if (this._fileExtra == Enums.FileType.EXTERNAL_DRIVE) { - return this._custom.get_icon(); - } - return this._fileInfo.get_icon(); - } - - _loadImageAsIcon(imageFile) { - if (this._loadThumbnailDataCancellable) { - this._loadThumbnailDataCancellable.cancel(); - } - this._loadThumbnailDataCancellable = new Gio.Cancellable(); - - return new Promise((resolve, reject) => { - imageFile.load_bytes_async(this._loadThumbnailDataCancellable, (source, result) => { - this._loadThumbnailDataCancellable = null; - try { - let [thumbnailData, etagOut] = source.load_bytes_finish(result); - let thumbnailStream = Gio.MemoryInputStream.new_from_bytes(thumbnailData); - let thumbnailPixbuf = GdkPixbuf.Pixbuf.new_from_stream(thumbnailStream, null); - - if (thumbnailPixbuf != null) { - let width = Prefs.get_desired_width() - 8; - let height = Prefs.get_icon_size() - 8; - let aspectRatio = thumbnailPixbuf.width / thumbnailPixbuf.height; - if ((width / height) > aspectRatio) { - width = height * aspectRatio; - } else { - height = width / aspectRatio; - } - const scale = this._icon.get_scale_factor(); - width *= scale; - height *= scale; - let pixbuf = thumbnailPixbuf.scale_simple(Math.floor(width), Math.floor(height), GdkPixbuf.InterpType.BILINEAR); - pixbuf = this._addEmblemsToPixbufIfNeeded(pixbuf); - let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); - this._icon.set_from_surface(surface); - this._icon.set_padding(4, 4); - resolve(true); - } - resolve(false); - } catch (e) { - resolve(false); - } - }); - }); - } - - _copyAndResizeIfNeeded(pixbuf) { - /** - * If the pixbuf is the original from the theme, copies it into a new one, to be able - * to paint the emblems without altering the cached pixbuf in the theme object. - * Also, ensures that the copied pixbuf is, at least, as big as the desired icon size, - * to ensure that the emblems fit. - */ - - if (this._copiedPixbuf) { - return pixbuf; - } - - this._copiedPixbuf = true; - let minsize = Prefs.get_icon_size(); - if ((pixbuf.width < minsize) || (pixbuf.height < minsize)) { - let width = pixbuf.width < minsize ? minsize : pixbuf.width; - let height = pixbuf.height < minsize ? minsize : pixbuf.height; - let newpixbuf = GdkPixbuf.Pixbuf.new(pixbuf.colorspace, true, pixbuf.bits_per_sample, width, height); - newpixbuf.fill(0); - let x = Math.floor((width - pixbuf.width) / 2); - let y = Math.floor((height - pixbuf.height) / 2); - pixbuf.composite(newpixbuf, x, y, pixbuf.width, pixbuf.height, x, y, 1, 1, GdkPixbuf.InterpType.NEAREST, 255); - return newpixbuf; - } else { - return pixbuf.copy(); - } - } - - _addEmblemsToPixbufIfNeeded(pixbuf) { - const scale = this._icon.get_scale_factor(); - this._copiedPixbuf = false; - let emblem = null; - let finalSize = Math.floor(Prefs.get_icon_size() / 3) * scale; - - if (this._isDesktopFile && (!this._isValidDesktopFile || !this.trustedDesktopFile)) { - pixbuf = this._copyAndResizeIfNeeded(pixbuf); - pixbuf.saturate_and_pixelate(pixbuf, 0.5, true); - emblem = Gio.ThemedIcon.new('emblem-unreadable'); - pixbuf = this._copyAndResizeIfNeeded(pixbuf); - let theme = Gtk.IconTheme.get_default(); - let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); - emblemIcon.composite(pixbuf, pixbuf.width - finalSize, pixbuf.height - finalSize, finalSize, finalSize, pixbuf.width - finalSize, pixbuf.height - finalSize, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); - } - - if (this._isSymlink && (this._desktopManager.showLinkEmblem || this._isBrokenSymlink)) { - if (this._isBrokenSymlink) { - emblem = Gio.ThemedIcon.new('emblem-unreadable'); - } else { - emblem = Gio.ThemedIcon.new('emblem-symbolic-link'); - } - pixbuf = this._copyAndResizeIfNeeded(pixbuf); - let theme = Gtk.IconTheme.get_default(); - let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); - emblemIcon.composite(pixbuf, pixbuf.width - finalSize, pixbuf.height - finalSize, finalSize, finalSize, pixbuf.width - finalSize, pixbuf.height - finalSize, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); - } - - if (this.isStackTop && !this.stackUnique) { - pixbuf = this._copyAndResizeIfNeeded(pixbuf); - let theme = Gtk.IconTheme.get_default(); - emblem = Gio.ThemedIcon.new('emblem-downloads'); - let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); - emblemIcon.composite(pixbuf, 0, 0, finalSize, finalSize, 0, 0, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); - } - return pixbuf; - } - - _createEmblemedIcon(icon, iconName) { - if (icon == null) { - if (GLib.path_is_absolute(iconName)) { - try { - let iconFile = Gio.File.new_for_commandline_arg(iconName); - icon = new Gio.FileIcon({file: iconFile}); - } catch (e) { - icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName); - } - } else { - icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName); - } - } - let theme = Gtk.IconTheme.get_default(); - - const scale = this._icon.get_scale_factor(); - let itemIcon = null; - try { - itemIcon = theme.lookup_by_gicon_for_scale(icon, Prefs.get_icon_size(), scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); - } catch (e) { - itemIcon = theme.load_icon_for_scale('text-x-generic', Prefs.get_icon_size(), scale, Gtk.IconLookupFlags.FORCE_SIZE); - } - - itemIcon = this._addEmblemsToPixbufIfNeeded(itemIcon); - - return itemIcon; - } - - /** ********************* - * Getters and setters * - ***********************/ - - get state() { - return this._state; - } - - set state(state) { - if (state == this._state) { - return; - } - - this._state = state; - } - - get isDrive() { - return this._fileExtra == Enums.FileType.EXTERNAL_DRIVE; - } - - get isSelected() { - return this._isSelected; - } - - get isSpecial() { - return this._isSpecial; - } - - get dropCoordinates() { - return this._dropCoordinates; - } - - set dropCoordinates(pos) { - this._dropCoordinates = pos; - } -}; -Signals.addSignalMethods(desktopIconItem.prototype); diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconsUtil.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconsUtil.js deleted file mode 100644 index d4fe808..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconsUtil.js +++ /dev/null @@ -1,356 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported getModifiersInDnD, getDesktopDir, getScriptsDir, getTemplatesDir, clamp, - spawnCommandLine, launchTerminal, getFilteredEnviron, distanceBetweenPoints, getExtraFolders, - getMounts, getFileExtensionOffset, getFilesFromNautilusDnD, writeTextFileToDesktop, - windowHidePagerTaskbarModal, waitDelayMs */ -'use strict'; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; -const Gdk = imports.gi.Gdk; -const Prefs = imports.preferences; -const Enums = imports.enums; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -/** - * - * @param context - * @param modifiersToCheck - */ -function getModifiersInDnD(context, modifiersToCheck) { - let device = context.get_device(); - let display = device.get_display(); - let keymap = Gdk.Keymap.get_for_display(display); - let modifiers = keymap.get_modifier_state(); - return (modifiers & modifiersToCheck) != 0; -} - -/** - * - */ -function getDesktopDir() { - let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); - return Gio.File.new_for_commandline_arg(desktopPath); -} - -/** - * - */ -function getScriptsDir() { - let scriptsDir = GLib.build_filenamev([GLib.get_home_dir(), Enums.NAUTILUS_SCRIPTS_DIR]); - return Gio.File.new_for_commandline_arg(scriptsDir); -} - -/** - * - */ -function getTemplatesDir() { - let templatesDir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_TEMPLATES); - if ((templatesDir == GLib.get_home_dir()) || (templatesDir == null)) { - return null; - } - return Gio.File.new_for_commandline_arg(templatesDir); -} - -/** - * - * @param value - * @param min - * @param max - */ -function clamp(value, min, max) { - return Math.max(Math.min(value, max), min); -} - -/** - * - * @param commandLine - * @param environ - */ -function spawnCommandLine(commandLine, environ = null) { - try { - let [success, argv] = GLib.shell_parse_argv(commandLine); - trySpawn(null, argv, environ); - } catch (err) { - print(`${commandLine} failed with ${err}`); - } -} - -/** - * - * @param workdir - * @param command - */ -function launchTerminal(workdir, command) { - let terminalSettings = new Gio.Settings({schema_id: Enums.TERMINAL_SCHEMA}); - let exec = terminalSettings.get_string(Enums.EXEC_KEY); - let argv = [exec, `--working-directory=${workdir}`]; - if (command) { - argv.push('-e'); - argv.push(command); - } - trySpawn(workdir, argv, null); -} - -/** - * - * @param workdir - * @param argv - * @param environ - */ -function trySpawn(workdir, argv, environ = null) { - /* The following code has been extracted from GNOME Shell's - * source code in Misc.Util.trySpawn function and modified to - * set the working directory. - * - * https://gitlab.gnome.org/GNOME/gnome-shell/blob/gnome-3-30/js/misc/util.js - */ - - var success, pid; - try { - [success, pid] = GLib.spawn_async(workdir, argv, environ, - GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, - null); - } catch (err) { - /* Rewrite the error in case of ENOENT */ - if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) { - throw new GLib.SpawnError({ - code: GLib.SpawnError.NOENT, - message: _('Command not found'), - }); - } else if (err instanceof GLib.Error) { - // The exception from gjs contains an error string like: - // Error invoking GLib.spawn_command_line_async: Failed to - // execute child process "foo" (No such file or directory) - // We are only interested in the part in the parentheses. (And - // we can't pattern match the text, since it gets localized.) - let message = err.message.replace(/.*\((.+)\)/, '$1'); - throw new err.constructor({ - code: err.code, - message, - }); - } else { - throw err; - } - } - // Dummy child watch; we don't want to double-fork internally - // because then we lose the parent-child relationship, which - // can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275 - GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, () => {}); -} - -/** - * - */ -function getFilteredEnviron() { - let environ = []; - for (let env of GLib.get_environ()) { - /* It's a must to remove the WAYLAND_SOCKET environment variable - because, under Wayland, DING uses an specific socket to allow the - extension to detect its windows. But the scripts must run under - the normal socket */ - if (env.startsWith('WAYLAND_SOCKET=')) { - continue; - } - environ.push(env); - } - return environ; -} - -/** - * - * @param x - * @param y - * @param x2 - * @param y2 - */ -function distanceBetweenPoints(x, y, x2, y2) { - return Math.pow(x - x2, 2) + Math.pow(y - y2, 2); -} - -/** - * - */ -function getExtraFolders() { - let extraFolders = []; - if (Prefs.desktopSettings.get_boolean('show-home')) { - extraFolders.push([Gio.File.new_for_commandline_arg(GLib.get_home_dir()), Enums.FileType.USER_DIRECTORY_HOME]); - } - if (Prefs.desktopSettings.get_boolean('show-trash')) { - extraFolders.push([Gio.File.new_for_uri('trash:///'), Enums.FileType.USER_DIRECTORY_TRASH]); - } - return extraFolders; -} - -/** - * - * @param volumeMonitor - */ -function getMounts(volumeMonitor) { - let showVolumes = Prefs.desktopSettings.get_boolean('show-volumes'); - let showNetwork = Prefs.desktopSettings.get_boolean('show-network-volumes'); - - try { - var mounts = volumeMonitor.get_mounts(); - } catch (e) { - print(`Failed to get the list of mounts with ${e}`); - return []; - } - - let result = []; - let uris = []; - for (let mount of mounts) { - try { - let isDrive = (mount.get_drive() != null) || (mount.get_volume() != null); - let uri = mount.get_default_location().get_uri(); - if (((isDrive && showVolumes) || (!isDrive && showNetwork)) && !uris.includes(uri)) { - result.push([mount.get_default_location(), Enums.FileType.EXTERNAL_DRIVE, mount]); - uris.push(uri); - } - } catch (e) { - print(`Failed with ${e} while getting volume`); - } - } - return result; -} - -/** - * - * @param filename - * @param opts - */ -function getFileExtensionOffset(filename, opts = {'isDirectory': false}) { - let offset = filename.length; - let extension = ''; - if (!opts.isDirectory) { - const doubleExtensions = ['.gz', '.bz2', '.sit', '.Z', '.bz', '.xz']; - for (const item of doubleExtensions) { - if (filename.endsWith(item)) { - offset -= item.length; - extension = filename.substring(offset); - filename = filename.substring(0, offset); - break; - } - } - let lastDot = filename.lastIndexOf('.'); - if (lastDot > 0) { - offset = lastDot; - extension = filename.substring(offset) + extension; - filename = filename.substring(0, offset); - } - } - return {offset, 'basename': filename, extension}; -} - -/** - * - * @param selection - * @param type - */ -function getFilesFromNautilusDnD(selection, type) { - let data = String.fromCharCode.apply(null, selection.get_data()); - let retval = []; - let elements = data.split('\r\n'); - for (let item of elements) { - if (item.length == 0) { - continue; - } - if (type == 1) { - // x-special/gnome-icon-list - let entry = item.split('\r'); - retval.push(entry[0]); - } else { - // text/uri-list - if (item[0] == '#') { - continue; - } - retval.push(item); - } - } - return retval; -} - -/** - * - * @param text - * @param filename - * @param dropCoordinates - */ -function writeTextFileToDesktop(text, filename, dropCoordinates) { - let path = GLib.build_filenamev([GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP), filename]); - let file = Gio.File.new_for_path(path); - const PERMISSIONS_MODE = 0o744; - if (GLib.mkdir_with_parents(file.get_parent().get_path(), PERMISSIONS_MODE) === 0) { - let [success, tag] = file.replace_contents(text, null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); - } - if (dropCoordinates != null) { - let info = new Gio.FileInfo(); - info.set_attribute_string('metadata::nautilus-drop-position', `${dropCoordinates[0]},${dropCoordinates[1]}`); - try { - file.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) {} - } -} - -/** - * - * @param window - * @param modal - */ -function windowHidePagerTaskbarModal(window, modal) { - let usingX11 = Gdk.Display.get_default().constructor.$gtype.name === 'GdkX11Display'; - if (usingX11) { - window.set_type_hint(Gdk.WindowTypeHint.NORMAL); - window.set_skip_taskbar_hint(true); - window.set_skip_pager_hint(true); - } else { - let title = window.get_title(); - if (title == null) { - title = ''; - } - if (modal) { - title += ' '; - } else { - title += ' '; - } - window.set_title(title); - } - if (modal) { - window.connect('focus-out-event', () => { - window.set_keep_above(true); - window.stick(); - window.grab_focus(); - }); - window.grab_focus(); - } -} - -/** - * - * @param ms - */ -function waitDelayMs(ms) { - return new Promise((resolve, reject) => { - GLib.timeout_add(GLib.PRIORITY_DEFAULT, ms, () => { - resolve(); - return false; - }); - }); -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopManager.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopManager.js deleted file mode 100644 index 58bb955..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopManager.js +++ /dev/null @@ -1,2367 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported DesktopManager */ -'use strict'; -const GLib = imports.gi.GLib; -const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; -const Gio = imports.gi.Gio; -const ByteArray = imports.byteArray; - -const FileItem = imports.fileItem; -const stackItem = imports.stackItem; -const DesktopGrid = imports.desktopGrid; -const DesktopIconsUtil = imports.desktopIconsUtil; -const Prefs = imports.preferences; -const Enums = imports.enums; -const NotifyX11UnderWayland = imports.notifyX11UnderWayland; -const DBusUtils = imports.dbusUtils; -const AskRenamePopup = imports.askRenamePopup; -const ShowErrorPopup = imports.showErrorPopup; -const TemplatesScriptsManager = imports.templatesScriptsManager; -const Thumbnails = imports.thumbnails; -const FileItemMenu = imports.fileItemMenu; -const AutoAr = imports.autoAr; - -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var DesktopManager = class { - constructor(mainApp, dbusManager, desktopList, codePath, asDesktop, primaryIndex) { - this.mainApp = mainApp; - this.using_X11 = Gdk.Display.get_default().constructor.$gtype.name === 'GdkX11Display'; - if (asDesktop) { - this.mainApp.hold(); // Don't close the application if there are no desktops - this._hold_active = true; - if (this.using_X11) { - let usingWayland = GLib.getenv('XDG_SESSION_TYPE') == 'wayland'; - if (usingWayland) { - // the system is using Wayland, but GTK is using X11!!!!!! - DBusUtils.extensionControl.activate_action('disableTimer', null); - if (Prefs.desktopSettings.get_boolean('check-x11wayland')) { - this._notifyX11UnderWayland = new NotifyX11UnderWayland.NotifyX11UnderWayland(doNotShowAnymore => { - this._notifyX11UnderWayland = null; - if (doNotShowAnymore) { - Prefs.desktopSettings.set_boolean('check-x11wayland', false); - } - }); - } - } - } else { - // if the problem is fixed and appears again, DING should show the message - Prefs.desktopSettings.set_boolean('check-x11wayland', true); - } - } - this._selectedFiles = null; - - this._premultiplied = false; - try { - for (let f of Prefs.mutterSettings.get_strv('experimental-features')) { - if (f == 'scale-monitor-framebuffer') { - this._premultiplied = true; - break; - } - } - } catch (e) { - } - - this.dbusManager = dbusManager; - this.autoAr = new AutoAr.AutoAr(this); - - this.templatesMonitor = new TemplatesScriptsManager.TemplatesScriptsManager( - DesktopIconsUtil.getTemplatesDir(), - TemplatesScriptsManager.TemplatesScriptsManagerFlags.HIDE_EXTENSIONS, - this._newDocument.bind(this) - ); - - this._primaryIndex = primaryIndex; - if (primaryIndex < desktopList.length) { - this._primaryScreen = desktopList[primaryIndex]; - } else { - this._primaryScreen = null; - } - this._clickX = 0; - this._clickY = 0; - this._dragList = null; - this.dragItem = null; - this.thumbnailLoader = new Thumbnails.ThumbnailLoader(codePath); - this._codePath = codePath; - this._asDesktop = asDesktop; - this._desktopList = desktopList; - this._desktops = []; - this._desktopFilesChanged = false; - this._readingDesktopFiles = false; - this._desktopDir = DesktopIconsUtil.getDesktopDir(); - this.desktopFsId = this._desktopDir.query_info('id::filesystem', Gio.FileQueryInfoFlags.NONE, null).get_attribute_string('id::filesystem'); - this._updateWritableByOthers(); - this._monitorDesktopDir = this._desktopDir.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); - this._monitorDesktopDir.set_rate_limit(1000); - this._monitorDesktopDir.connect('changed', (obj, file, otherFile, eventType) => this._updateDesktopIfChanged(file, otherFile, eventType)); - - this.fileItemMenu = new FileItemMenu.FileItemMenu(this); - if (Prefs.schemaGnomeDarkSettings) { - if (this._checkApplyDarkModeSetting()) { - Prefs.schemaGnomeDarkSettings.connect('changed', (obj, key) => { - if (key === 'color-scheme') { - this._checkApplyDarkModeSetting(); - } - }); - } - } - this._showHidden = Prefs.gtkSettings.get_boolean('show-hidden'); - this.showDropPlace = Prefs.desktopSettings.get_boolean('show-drop-place'); - this.useNemo = Prefs.desktopSettings.get_boolean('use-nemo'); - this.showLinkEmblem = Prefs.desktopSettings.get_boolean('show-link-emblem'); - this.darkText = Prefs.desktopSettings.get_boolean('dark-text-in-labels'); - this._settingsId = Prefs.desktopSettings.connect('changed', (obj, key) => { - if (key == 'dark-text-in-labels') { - this.darkText = Prefs.desktopSettings.get_boolean('dark-text-in-labels'); - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Dark Text changed: ${e.message}\n${e.stack}`); - }); - return; - } - if (key == 'show-link-emblem') { - this.showLinkEmblem = Prefs.desktopSettings.get_boolean('show-link-emblem'); - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Show Emblems changed: ${e.message}\n${e.stack}`); - }); - return; - } - if (key == 'use-nemo') { - this.useNemo = Prefs.desktopSettings.get_boolean('use-nemo'); - return; - } - if (key == 'icon-size') { - this._fileList.forEach(x => x.removeFromGrid(false)); - for (let desktop of this._desktops) { - desktop.resizeGrid(); - } - this._fileList.forEach(x => x.updateIcon()); - this._placeAllFilesOnGrids(true); - return; - } - if (key == Enums.SortOrder.ORDER) { - this.doArrangeRadioButtons(); - if (this.keepStacked) { - this.doStacks(true); - } else { - this.doSorts(true); - } - return; - } - if (key == 'unstackedtypes') { - if (this.keepStacked) { - this.doStacks(true); - } - return; - } - if (key == 'keep-stacked') { - this.keepStacked = Prefs.desktopSettings.get_boolean('keep-stacked'); - if (!this.keepStacked) { - this._unstack(); - } else { - this.doStacks(true); - } - return; - } - if (key == 'keep-arranged') { - this.keepArranged = Prefs.desktopSettings.get_boolean('keep-arranged'); - if (this.keepArranged) { - this.doSorts(true); - } - return; - } - this.showDropPlace = Prefs.desktopSettings.get_boolean('show-drop-place'); - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Settings Changed: ${e.message}\n${e.stack}`); - }); - }); - Prefs.gtkSettings.connect('changed', (obj, key) => { - if (key == 'show-hidden') { - this._showHidden = Prefs.gtkSettings.get_boolean('show-hidden'); - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Hidden Settings Changed: ${e.message}\n${e.stack}`); - }); - } - }); - Prefs.nautilusSettings.connect('changed', (obj, key) => { - if (key == 'show-image-thumbnails') { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Nautilus Settings Changed: ${e.message}\n${e.stack}`); - }); - } - }); - this._gtkIconTheme = Gtk.IconTheme.get_default(); - this._gtkIconTheme.connect('changed', () => { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after Gtk Icon Theme Change: ${e.message}\n${e.stack}`); - }); - }); - this._volumeMonitor = Gio.VolumeMonitor.get(); - this._volumeMonitor.connect('mount-added', () => { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after mount added: ${e.message}\n${e.stack}`); - }); - }); - this._volumeMonitor.connect('mount-removed', () => { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after mount removed: ${e.message}\n${e.stack}`); - }); - }); - - this.rubberBand = false; - - let cssProvider = new Gtk.CssProvider(); - cssProvider.load_from_file(Gio.File.new_for_path(GLib.build_filenamev([codePath, 'stylesheet.css']))); - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - cssProvider = undefined; - this._configureSelectionColor(); - this._createDesktopBackgroundMenu(); - this._createGridWindows(); - - DBusUtils.NautilusFileOperations2.connectToProxy('g-properties-changed', this._undoStatusChanged.bind(this)); - DBusUtils.GtkVfsMetadata.connectSignalToProxy('AttributeChanged', this._metadataChanged.bind(this)); - this._allFileList = null; - this._fileList = []; - this._forcedExit = false; - this._updateDesktop().catch(e => { - print(`Exception while Initiating Desktop: ${e.message}\n${e.stack}`); - }); - - this._scriptsList = []; - - this.ignoreKeys = [Gdk.KEY_space, Gdk.KEY_Shift_L, Gdk.KEY_Shift_R, Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Caps_Lock, Gdk.KEY_Shift_Lock, Gdk.KEY_Meta_L, Gdk.KEY_Meta_R, Gdk.KEY_Alt_L, Gdk.KEY_Alt_R, Gdk.KEY_Super_L, Gdk.KEY_Super_R, Gdk.KEY_ISO_Level3_Shift, Gdk.KEY_ISO_Level5_Shift]; - - - // Check if Nautilus is available - try { - DesktopIconsUtil.trySpawn(null, ['nautilus', '--version']); - } catch (e) { - this._errorWindow = new ShowErrorPopup.ShowErrorPopup(_('Nautilus File Manager not found'), - _('The Nautilus File Manager is mandatory to work with Desktop Icons NG.'), - true); - } - this._pendingDropFiles = {}; - if (this._asDesktop) { - this._sigtermID = GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, 15, () => { - GLib.source_remove(this._sigtermID); - for (let desktop of this._desktops) { - desktop.destroy(); - } - this._desktops = []; - this._forcedExit = true; - if (this._desktopEnumerateCancellable) { - this._desktopEnumerateCancellable.cancel(); - } - if (this._hold_active) { - this.mainApp.release(); - this._hold_active = false; - } - return false; - }); - } - if (this._asDesktop) { - this._dbusAdvertiseUpdate(); - } - let changeDesktopIconSettings = Gio.SimpleAction.new('changeDesktopIconSettings', null); - changeDesktopIconSettings.connect('activate', () => Prefs.showPreferences()); - this.mainApp.add_action(changeDesktopIconSettings); - } - - _metadataChanged(proxy, nameOwner, args) { - let filepath = GLib.build_filenamev([GLib.get_home_dir(), args[1]]); - if (this._desktopDir.get_path() === GLib.path_get_dirname(filepath)) { - for (let fileItem of this.updateFileList()) { - if (fileItem.path == filepath) { - fileItem.updatedMetadata(); - break; - } - } - } - } - - updateFileList() { - let updateFileList; - if (this._allFileList && (this._allFileList.length > 0)) { - updateFileList = this._allFileList; - } else { - updateFileList = this._fileList; - } - return updateFileList; - } - - _dbusAdvertiseUpdate() { - DBusUtils.extensionControl.connect('action-state-changed', (actionGroup, actionName, data) => { - if (actionName == 'desktopGeometry') { - this.updateGridWindows(data.recursiveUnpack()); - } - }); - DBusUtils.extensionControl.connect('action-added', (actionGroup, actionName) => { - // this signal allows us to know when the action is available and we can read the initial value - if (actionName == 'desktopGeometry') { - let data = DBusUtils.extensionControl.get_action_state('desktopGeometry'); - this.updateGridWindows(data.recursiveUnpack()); - } - }); - // This is required to trigger the 'action-added' signal - DBusUtils.extensionControl.list_actions(); - } - - updateGridWindows(newdesktoplist) { - if ((newdesktoplist.length > 0) && ('primaryMonitor' in newdesktoplist[0])) { - this._primaryIndex = newdesktoplist[0].primaryMonitor; - } - if (newdesktoplist.length != this._desktopList.length) { - this._fileList.forEach(x => x.removeFromGrid(false)); - this._desktopList = newdesktoplist; - if (this._primaryIndex < this._desktopList.length) { - this._primaryScreen = this._desktopList[this._primaryIndex]; - } else { - this._primaryScreen = null; - } - this._createGridWindows(); - this._placeAllFilesOnGrids(true); - return; - } - let monitorschanged = []; - let gridschanged = []; - for (let index = 0; index < newdesktoplist.length; index++) { - let area = newdesktoplist[index]; - let area2 = this._desktopList[index]; - if ((area.x != area2.x) || - (area.y != area2.y) || - (area.width != area2.width) || - (area.height != area2.height) || - (area.zoom != area2.zoom) || - (area.monitorIndex != area2.monitorIndex)) { - monitorschanged.push(index); - gridschanged.push(index); - continue; - } - if ((area.marginTop != area2.marginTop) || - (area.marginBottom != area2.marginBottom) || - (area.marginLeft != area2.marginLeft) || - (area.marginRight != area2.marginRight)) { - if (!gridschanged.includes(index)) { - gridschanged.push(index); - } - } - } - if (gridschanged.length > 0) { - this._fileList.forEach(x => x.removeFromGrid(false)); - for (let gridindex of gridschanged) { - let desktop = this._desktops[gridindex]; - desktop.updateGridDescription(newdesktoplist[gridindex]); - if (monitorschanged.includes(gridindex)) { - desktop.resizeWindow(); - } - desktop.resizeGrid(); - } - this._desktopList = newdesktoplist; - this._placeAllFilesOnGrids(true); - } - if (this._primaryIndex < this._desktopList.length) { - this._primaryScreen = this._desktopList[this._primaryIndex]; - } else { - this._primaryScreen = null; - } - } - - _createGridWindows() { - for (let desktop of this._desktops) { - desktop.destroy(); - } - this._desktops = []; - for (let desktopIndex in this._desktopList) { - let desktop = this._desktopList[desktopIndex]; - let desktopName; - if (this._asDesktop) { - desktopName = `@!${desktop.x},${desktop.y};BDHF`; - } else { - desktopName = `DING ${desktopIndex}`; - } - this._desktops.push(new DesktopGrid.DesktopGrid(this, desktopName, desktop, this._asDesktop, this._premultiplied)); - } - } - - _configureSelectionColor() { - this._contextWidget = new Gtk.WidgetPath(); - this._contextWidget.append_type(Gtk.Widget); - - this._styleContext = new Gtk.StyleContext(); - this._styleContext.set_path(this._contextWidget); - this._styleContext.add_class('view'); - this._cssProviderSelection = new Gtk.CssProvider(); - this._styleContext.connect('changed', () => { - Gtk.StyleContext.remove_provider_for_screen(Gdk.Screen.get_default(), this._cssProviderSelection); - this._setSelectionColor(); - }); - this._setSelectionColor(); - } - - _setSelectionColor() { - this.selectColor = this._styleContext.get_background_color(Gtk.StateFlags.SELECTED); - let style = `.desktop-icons-selected { - background-color: rgba(${this.selectColor.red * 255},${this.selectColor.green * 255}, ${this.selectColor.blue * 255}, 0.6); - }`; - this._cssProviderSelection.load_from_data(style); - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), this._cssProviderSelection, 600); - } - - _checkApplyDarkModeSetting() { - try { - let displayGtkSettings = Gtk.Settings.get_for_screen(Gdk.Screen.get_default()); - displayGtkSettings.gtk_application_prefer_dark_theme = Prefs.schemaGnomeDarkSettings.get_string('color-scheme') === 'prefer-dark'; - return true; - } catch (e) { - return false; - } - } - - clearFileCoordinates(fileList, dropCoordinates) { - for (let element of fileList) { - let file = Gio.File.new_for_uri(element); - if (!file.is_native() || !file.query_exists(null)) { - if (dropCoordinates != null) { - this._pendingDropFiles[file.get_basename()] = dropCoordinates; - } - continue; - } - let info = new Gio.FileInfo(); - info.set_attribute_string('metadata::nautilus-icon-position', ''); - if (dropCoordinates != null) { - info.set_attribute_string('metadata::nautilus-drop-position', `${dropCoordinates[0]},${dropCoordinates[1]}`); - } - try { - file.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) {} - } - } - - doMoveWithDragAndDrop(xOrigin, yOrigin, xDestination, yDestination) { - let keepArranged = this.keepArranged || this.keepStacked; - if (this.sortSpecialFolders && keepArranged) { - return; - } - // Find the grid where the destination lies and aim towards the positive side, middle of grid to ensure drop in the grid - for (let desktop of this._desktops) { - let grid = desktop.getGridAt(xDestination, yDestination, true); - if (grid !== null) { - xDestination = grid[0] + desktop._elementWidth / 2; - yDestination = grid[1] + desktop._elementHeight / 2; - break; - } - } - let deltaX = xDestination - xOrigin; - let deltaY = yDestination - yOrigin; - let fileItems = []; - for (let item of this._fileList) { - if (item.isSelected) { - if (keepArranged) { - if (item.isSpecial) { - fileItems.push(item); - item.removeFromGrid(false); - let [x, y, a, b, c] = item.getCoordinates(); - item.savedCoordinates = [x + deltaX, y + deltaY]; - } else { - continue; - } - } else { - fileItems.push(item); - item.removeFromGrid(false); - let [x, y, a, b, c] = item.getCoordinates(); - item.savedCoordinates = [x + deltaX, y + deltaY]; - } - } - } - // force to store the new coordinates - this._addFilesToDesktop(fileItems, Enums.StoredCoordinates.OVERWRITE); - fileItems = undefined; - if (this.keepArranged) { - this._updateDesktop().catch(e => { - print(`Exception while doing move with drag and drop and keeping arranged: ${e.message}\n${e.stack}`); - }); - } - } - - onDragBegin(item) { - this.dragItem = item; - } - - onDragMotion(x, y) { - if (this.dragItem === null) { - for (let desktop of this._desktops) { - desktop.refreshDrag([[0, 0]], x, y); - } - return; - } - if (this._dragList === null) { - let itemList = this.getCurrentSelection(false); - if (!itemList) { - return; - } - let [x1, y1, x2, y2, c] = this.dragItem.getCoordinates(); - let oX = x1; - let oY = y1; - this._dragList = []; - for (let item of itemList) { - [x1, y1, x2, y2, c] = item.getCoordinates(); - this._dragList.push([x1 - oX, y1 - oY]); - } - } - for (let desktop of this._desktops) { - desktop.refreshDrag(this._dragList, x, y); - } - } - - onDragLeave() { - this._dragList = null; - for (let desktop of this._desktops) { - desktop.refreshDrag(null, 0, 0); - } - } - - onDragEnd() { - this.dragItem = null; - } - - onDragDataReceived(context, xDestination, yDestination, selection, info, forceLocal, forceCopy) { - this.onDragLeave(); - let fileList = DesktopIconsUtil.getFilesFromNautilusDnD(selection, info); - if (forceLocal) { - info = Enums.DndTargetInfo.DING_ICON_LIST; - } - switch (info) { - case Enums.DndTargetInfo.DING_ICON_LIST: - if (fileList.length != 0) { - let [xOrigin, yOrigin, a, b, c] = this.dragItem.getCoordinates(); - this.doMoveWithDragAndDrop(xOrigin, yOrigin, xDestination, yDestination); - Gtk.drag_finish(context, true, true, Gtk.get_current_event_time()); - } - break; - case Enums.DndTargetInfo.GNOME_ICON_LIST: - case Enums.DndTargetInfo.URI_LIST: - if (fileList.length != 0) { - this.clearFileCoordinates(fileList, [xDestination, yDestination]); - let data = Gio.File.new_for_uri(fileList[0]).query_info('id::filesystem', Gio.FileQueryInfoFlags.NONE, null); - let idFS = data.get_attribute_string('id::filesystem'); - if ((this.desktopFsId == idFS) && !forceCopy) { - DBusUtils.RemoteFileOperations.MoveURIsRemote(fileList, `file://${GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)}`); - Gtk.drag_finish(context, true, true, Gtk.get_current_event_time()); - } else { - DBusUtils.RemoteFileOperations.CopyURIsRemote(fileList, `file://${GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)}`); - Gtk.drag_finish(context, true, false, Gtk.get_current_event_time()); - } - } else { - Gtk.drag_finish(context, false, false, Gtk.get_current_event_time()); - } - break; - case Enums.DndTargetInfo.TEXT_PLAIN: - if (fileList.length != 0) { - let dropCoordinates = [xDestination, yDestination]; - this.detectURLorText(fileList, dropCoordinates); - Gtk.drag_finish(context, true, false, Gtk.get_current_event_time()); - } else { - Gtk.drag_finish(context, false, false, Gtk.get_current_event_time()); - } - break; - - default: - Gtk.drag_finish(context, false, false, Gtk.get_current_event_time()); - break; - } - } - - detectURLorText(fileList, dropCoordinates) { - /** - * - * @param str - */ - function isValidURL(str) { - var pattern = new RegExp('^(https|http|ftp|rtsp|mms)?:\\/\\/?' + - '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + - '((\\d{1,3}\\.){3}\\d{1,3}))' + - '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + - '(\\?[;&a-z\\d%_.~+=-]*)?' + - '(\\#[-a-z\\d_]*)?$', 'i'); - return !!pattern.test(str); - } - let text = fileList.toString(); - if (isValidURL(text)) { - this.writeURLlinktoDesktop(text, dropCoordinates); - } else { - let filename = 'Dragged Text'; - let now = Date().valueOf().split(' ').join('').replace(/:/g, '-'); - filename = `${filename}-${now}`; - DesktopIconsUtil.writeTextFileToDesktop(text, filename, dropCoordinates); - } - } - - writeURLlinktoDesktop(link, dropCoordinates) { - let filename = link.split('?')[0]; - filename = filename.split('//')[1]; - filename = filename.split('/')[0]; - let now = Date().valueOf().split(' ').join('').replace(/:/g, '-'); - filename = `${filename}-${now}`; - this.writeHTMLTypeLink(filename, link, dropCoordinates); - } - - - writeHTMLTypeLink(filename, link, dropCoordinates) { - filename += '.html'; - let body = ['', '', ``, '', '', '', '']; - body = body.join('\n'); - DesktopIconsUtil.writeTextFileToDesktop(body, filename, dropCoordinates); - } - - fillDragDataGet(info) { - let fileList = this.getCurrentSelection(false); - if (fileList == null) { - return null; - } - let atom; - switch (info) { - case Enums.DndTargetInfo.DING_ICON_LIST: - atom = Gdk.atom_intern('x-special/ding-icon-list', false); - break; - case Enums.DndTargetInfo.GNOME_ICON_LIST: - atom = Gdk.atom_intern('x-special/gnome-icon-list', false); - break; - case Enums.DndTargetInfo.URI_LIST: - atom = Gdk.atom_intern('text/uri-list', false); - break; - default: - return null; - } - let data = ''; - for (let fileItem of fileList) { - data += fileItem.uri; - if (info === Enums.DndTargetInfo.GNOME_ICON_LIST) { - let coordinates = fileItem.getCoordinates(); - if (coordinates != null) { - data += `\r${coordinates[0]}:${coordinates[1]}:${coordinates[2] - coordinates[0] + 1}:${coordinates[3] - coordinates[1] + 1}`; - } - } - data += '\r\n'; - } - return [atom, data]; - } - - onPressButton(x, y, event, grid) { - this._clickX = Math.floor(x); - this._clickY = Math.floor(y); - let button = event.get_button()[1]; - let state = event.get_state()[1]; - if (button == 1) { - let shiftPressed = !!(state & Gdk.ModifierType.SHIFT_MASK); - let controlPressed = !!(state & Gdk.ModifierType.CONTROL_MASK); - if (!shiftPressed && !controlPressed) { - // clear selection - this.unselectAll(); - } - this._startRubberband(x, y); - } - if (button == 3) { - this._prepareMenu(); - this._menu.popup_at_pointer(event); - } - } - - _prepareMenu() { - let templates = this.templatesMonitor.createMenu(); - if (templates === null) { - this._newDocumentItem.hide(); - } else { - this._newDocumentItem.set_submenu(templates); - this._newDocumentItem.show_all(); - } - this._pasteMenuItem.set_sensitive(false); - this._syncUndoRedo(); - this._updateClipBoard(); - } - - _updateClipBoard() { - let atom = Gdk.Atom.intern('CLIPBOARD', false); - let atom2 = Gdk.Atom.intern('x-special/gnome-copied-files', false); - let clipboard = Gtk.Clipboard.get(atom); - this._isCut = false; - this._clipboardFiles = null; - let text = null; - /* - * Before Gnome Shell 40, St API couldn't access binary data in the clipboard, only text data. Also, the - * original Desktop Icons was a pure extension, so it was limited to what Clutter and St offered. That was - * the reason why Nautilus accepted a text format for CUT and COPY operations in the form - * - * x-special/nautilus-clipboard - * OPERATION - * FILE_URI - * [FILE_URI] - * [...] - * - * In Gnome Shell 40, St was enhanced and now it supports binary data; that's why Nautilus migrated to a - * binary format identified by the atom 'x-special/gnome-copied-files', where the CUT or COPY operation is - * shared. - * - * To maintain compatibility, we first check if there's binary data in that atom, and if not, we check if - * there is text data in the old format. - */ - if (clipboard.wait_is_target_available(atom2)) { - let data = clipboard.wait_for_contents(atom2); - text = `x-special/nautilus-clipboard\n${ByteArray.toString(data.get_data())}\n`; - } else { - text = clipboard.wait_for_text(); - if (text && !text.endsWith('\n')) { - text += '\n'; - } - } - this._setClipboardContent(text); - } - - _setClipboardContent(text) { - let [valid, isCut, files] = this._parseClipboardText(text); - if (valid) { - this._isCut = isCut; - this._clipboardFiles = files; - } - this._pasteMenuItem.set_sensitive(valid); - } - - _syncUndoRedo() { - if (!DBusUtils.RemoteFileOperations.isAvailable) { - this._undoMenuItem.hide(); - this._redoMenuItem.hide(); - return; - } - switch (DBusUtils.RemoteFileOperations.UndoStatus()) { - case Enums.UndoStatus.UNDO: - this._undoMenuItem.show(); - this._redoMenuItem.hide(); - break; - case Enums.UndoStatus.REDO: - this._undoMenuItem.hide(); - this._redoMenuItem.show(); - break; - default: - this._undoMenuItem.hide(); - this._redoMenuItem.hide(); - break; - } - } - - _undoStatusChanged(proxy, properties, test) { - if ('UndoStatus' in properties.deep_unpack()) { - this._syncUndoRedo(); - } - } - - _doUndo() { - DBusUtils.RemoteFileOperations.UndoRemote(); - } - - _doRedo() { - DBusUtils.RemoteFileOperations.RedoRemote(); - } - - onKeyPress(event, grid) { - let symbol = event.get_keyval()[1]; - let isCtrl = (event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) != 0; - let isShift = (event.get_state()[1] & Gdk.ModifierType.SHIFT_MASK) != 0; - let isAlt = (event.get_state()[1] & Gdk.ModifierType.MOD1_MASK) != 0; - let selection = this.getCurrentSelection(false); - if (isCtrl && isShift && ((symbol == Gdk.KEY_Z) || (symbol == Gdk.KEY_z))) { - this._doRedo(); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_Z) || (symbol == Gdk.KEY_z))) { - this._doUndo(); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_C) || (symbol == Gdk.KEY_c))) { - this.doCopy(); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_X) || (symbol == Gdk.KEY_x))) { - this.doCut(); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_V) || (symbol == Gdk.KEY_v))) { - this._updateClipBoard(); - this._doPaste(); - return true; - } else if (isAlt && (symbol == Gdk.KEY_Return)) { - let currentSelection = this.getCurrentSelection(true); - DBusUtils.RemoteFileOperations.ShowItemPropertiesRemote(currentSelection, event.get_time()); - return true; - } else if (symbol == Gdk.KEY_Return) { - if (selection && (selection.length == 1)) { - selection[0].doOpen(); - return true; - } - } else if (symbol == Gdk.KEY_Delete) { - if (isShift) { - this.doDeletePermanently(); - } else { - this.doTrash(); - } - return true; - } else if (symbol == Gdk.KEY_F2) { - if (selection && (selection.length == 1)) { - // Support renaming other grids file items. - this.doRename(selection[0], false); - return true; - } - } else if (selection && symbol == Gdk.KEY_space) { - // Support previewing other grids file items. - DBusUtils.RemoteFileOperations.ShowFileRemote(selection[0].uri, 0, true); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_A) || (symbol == Gdk.KEY_a))) { - this._selectAll(); - return true; - } else if (symbol == Gdk.KEY_F5) { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop after pressing F5: ${e.message}\n${e.stack}`); - }); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_H) || (symbol == Gdk.KEY_h))) { - Prefs.gtkSettings.set_boolean('show-hidden', !this._showHidden); - return true; - } else if (isCtrl && ((symbol == Gdk.KEY_F) || (symbol == Gdk.KEY_f))) { - this.findFiles(); - return true; - } else if (symbol == Gdk.KEY_Escape) { - this.unselectAll(); - if (this.searchString) { - this.searchString = null; - } - return true; - } else if (isCtrl && isShift && ((symbol == Gdk.KEY_N) || (symbol == Gdk.KEY_n))) { - this.doNewFolder(); - return true; - } else if (symbol == Gdk.KEY_Menu) { - if (selection) { - this.fileItemMenu.showMenu(selection[0], event, true); - } else { - this._prepareMenu(); - this._menu.popup_at_pointer(event); - } - return true; - } else if ((symbol == Gdk.KEY_Left) || (symbol == Gdk.KEY_Right) || - (symbol == Gdk.KEY_Up) || (symbol == Gdk.KEY_Down)) { - if (!selection) { - selection = this._fileList; - } - if (!selection) { - return false; - } - let selected = selection[0]; - let selectedCoordinates = selected.getCoordinates(); - this.unselectAll(); - if (selection.length > 1) { - for (let item of selection) { - let itemCoordinates = item.getCoordinates(); - if (itemCoordinates[0] > selectedCoordinates[0]) { - continue; - } - if ((itemCoordinates[0] < selectedCoordinates[0]) || - (itemCoordinates[1] < selectedCoordinates[1])) { - selected = item; - selectedCoordinates = itemCoordinates; - continue; - } - } - } - let index; - let multiplier; - switch (symbol) { - case Gdk.KEY_Left: - index = 0; - multiplier = -1; - break; - case Gdk.KEY_Right: - index = 0; - multiplier = 1; - break; - case Gdk.KEY_Up: - index = 1; - multiplier = -1; - break; - case Gdk.KEY_Down: - index = 1; - multiplier = 1; - break; - } - let newDistance = null; - let newItem = null; - for (let item of this._fileList) { - let itemCoordinates = item.getCoordinates(); - if ((selectedCoordinates[index] * multiplier) >= (itemCoordinates[index] * multiplier)) { - continue; - } - let distance = Math.pow(selectedCoordinates[0] - itemCoordinates[0], 2) + Math.pow(selectedCoordinates[1] - itemCoordinates[1], 2); - if ((newDistance === null) || (newDistance > distance)) { - newDistance = distance; - newItem = item; - } - } - if (newItem === null) { - newItem = selected; - } - newItem.setSelected(); - return false; - } else { - if (this.ignoreKeys.includes(symbol)) { - return false; - } - let key = String.fromCharCode(Gdk.keyval_to_unicode(symbol)); - if (this.keypressTimeoutID && this.searchString) { - this.searchString = this.searchString.concat(key); - } else { - this.searchString = key; - } - if (this.searchString != '') { - let found = this.scanForFiles(this.searchString, false); - if (found) { - if ((this.getNumberOfSelectedItems() >= 1) && !this.keypressTimeoutID) { - let windowError = new ShowErrorPopup.ShowErrorPopup( - _('Clear Current Selection before New Search'), - null, - true); - windowError.timeoutClose(2000); - return true; - } - this.searchEventTime = GLib.get_monotonic_time(); - if (!this.keypressTimeoutID) { - this.keypressTimeoutID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => { - if (GLib.get_monotonic_time() - this.searchEventTime < 1500000) { - return true; - } - this.searchString = null; - this.keypressTimeoutID = null; - if (this._findFileWindow) { - this._findFileWindow.response(Gtk.ResponseType.OK); - } - return false; - }); - } - this.findFiles(this.searchString); - } - } - return true; - } - return false; - } - - unselectAll() { - this._fileList.map(f => f.unsetSelected()); - } - - findFiles(text) { - this._findFileWindow = new Gtk.Dialog({ - use_header_bar: true, - window_position: Gtk.WindowPosition.CENTER_ON_PARENT, - resizable: false, - }); - this._findFileButton = this._findFileWindow.add_button(_('OK'), Gtk.ResponseType.OK); - this._findFileButton.sensitive = false; - this._findFileWindow.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - this._findFileWindow.set_modal(true); - this._findFileWindow.set_title(_('Find Files on Desktop')); - DesktopIconsUtil.windowHidePagerTaskbarModal(this._findFileWindow, true); - let contentArea = this._findFileWindow.get_content_area(); - this._findFileTextArea = new Gtk.Entry(); - contentArea.pack_start(this._findFileTextArea, true, true, 5); - contentArea = undefined; - this._findFileTextArea.connect('activate', () => { - if (this._findFileButton.sensitive) { - this._findFileWindow.response(Gtk.ResponseType.OK); - } - }); - this._findFileTextArea.connect('changed', () => { - let context = this._findFileTextArea.get_style_context(); - if (this.scanForFiles(this._findFileTextArea.text, true)) { - this._findFileButton.sensitive = true; - if (context.has_class('not-found')) { - context.remove_class('not-found'); - } - } else { - this._findFileButton.sensitive = false; - this._findFileTextArea.error_bell(); - if (!context.has_class('not-found')) { - context.add_class('not-found'); - } - } - this.searchEventTime = GLib.get_monotonic_time(); - }); - this._findFileTextArea.grab_focus_without_selecting(); - if (text) { - this._findFileTextArea.set_text(text); - this._findFileTextArea.set_position(text.length); - } else { - this.scanForFiles(null); - } - this._findFileWindow.show_all(); - this._findFileWindow.connect('close', () => { - this._findFileWindow.response(Gtk.ResponseType.CANCEL); - }); - this._findFileWindow.connect('response', (actor, retval) => { - if (retval == Gtk.ResponseType.CANCEL) { - this.unselectAll(); - } - this._findFileWindow.destroy(); - this._findFileWindow = null; - }); - } - - scanForFiles(text, setselected) { - let found = []; - if (text && (text != '')) { - found = this._fileList.filter(f => f.fileName.toLowerCase().includes(text.toLowerCase()) || f._label.get_text().toLowerCase().includes(text.toLowerCase())); - } - if (found.length != 0) { - if (setselected) { - this.unselectAll(); - found.map(f => f.setSelected()); - } - return true; - } else { - return false; - } - } - - _createDesktopBackgroundMenu() { - this._menu = new Gtk.Menu(); - this._menu.get_style_context().add_class('desktopmenu'); - let newFolder = new Gtk.MenuItem({label: _('New Folder')}); - newFolder.connect('activate', () => this.doNewFolder()); - this._menu.add(newFolder); - - this._newDocumentItem = new Gtk.MenuItem({label: _('New Document')}); - this._menu.add(this._newDocumentItem); - - this._menu.add(new Gtk.SeparatorMenuItem()); - - this._pasteMenuItem = new Gtk.MenuItem({label: _('Paste')}); - this._pasteMenuItem.connect('activate', () => this._doPaste()); - this._menu.add(this._pasteMenuItem); - - this._undoMenuItem = new Gtk.MenuItem({label: _('Undo')}); - this._undoMenuItem.connect('activate', () => this._doUndo()); - this._menu.add(this._undoMenuItem); - - this._redoMenuItem = new Gtk.MenuItem({label: _('Redo')}); - this._redoMenuItem.connect('activate', () => this._doRedo()); - this._menu.add(this._redoMenuItem); - - this._menu.add(new Gtk.SeparatorMenuItem()); - - let selectAll = new Gtk.MenuItem({label: _('Select All')}); - selectAll.connect('activate', () => this._selectAll()); - this._menu.add(selectAll); - - this._addSortingMenu(); - - this._menu.add(new Gtk.SeparatorMenuItem()); - - this._showDesktopInFilesMenuItem = new Gtk.MenuItem({label: _('Show Desktop in Files')}); - this._showDesktopInFilesMenuItem.connect('activate', () => this._onOpenDesktopInFilesClicked()); - this._menu.add(this._showDesktopInFilesMenuItem); - - this._openTerminalMenuItem = new Gtk.MenuItem({label: _('Open in Terminal')}); - this._openTerminalMenuItem.connect('activate', () => this._onOpenTerminalClicked()); - this._menu.add(this._openTerminalMenuItem); - - this._menu.add(new Gtk.SeparatorMenuItem()); - - this._changeBackgroundMenuItem = new Gtk.MenuItem({label: _('Change Background…')}); - this._changeBackgroundMenuItem.connect('activate', () => { - let desktopFile = Gio.DesktopAppInfo.new('gnome-background-panel.desktop'); - const context = Gdk.Display.get_default().get_app_launch_context(); - context.set_timestamp(Gtk.get_current_event_time()); - desktopFile.launch([], context); - }); - this._menu.add(this._changeBackgroundMenuItem); - - this._menu.add(new Gtk.SeparatorMenuItem()); - - this._settingsMenuItem = new Gtk.MenuItem({label: _('Desktop Icons Settings')}); - this._settingsMenuItem.connect('activate', () => Prefs.showPreferences()); - this._menu.add(this._settingsMenuItem); - - this._displaySettingsMenuItem = new Gtk.MenuItem({label: _('Display Settings')}); - this._displaySettingsMenuItem.connect('activate', () => { - let desktopFile = Gio.DesktopAppInfo.new('gnome-display-panel.desktop'); - const context = Gdk.Display.get_default().get_app_launch_context(); - context.set_timestamp(Gtk.get_current_event_time()); - desktopFile.launch([], context); - }); - this._menu.add(this._displaySettingsMenuItem); - - this._menu.show_all(); - } - - _selectAll() { - for (let fileItem of this._fileList) { - if (fileItem.isAllSelectable) { - fileItem.setSelected(); - } - } - } - - _onOpenDesktopInFilesClicked() { - const context = Gdk.Display.get_default().get_app_launch_context(); - context.set_timestamp(Gtk.get_current_event_time()); - Gio.AppInfo.launch_default_for_uri_async(this._desktopDir.get_uri(), - context, null, - (source, result) => { - try { - Gio.AppInfo.launch_default_for_uri_finish(result); - } catch (e) { - log(`Error opening Desktop in Files: ${e.message}`); - } - } - ); - } - - _onOpenTerminalClicked() { - let desktopPath = this._desktopDir.get_path(); - DesktopIconsUtil.launchTerminal(desktopPath, null); - } - - _doPaste() { - if (this._clipboardFiles === null) { - return; - } - - let desktopDir = this._desktopDir.get_uri(); - if (this._isCut) { - DBusUtils.RemoteFileOperations.MoveURIsRemote(this._clipboardFiles, desktopDir); - } else { - DBusUtils.RemoteFileOperations.CopyURIsRemote(this._clipboardFiles, desktopDir); - } - } - - _parseClipboardText(text) { - if (text === null) { - return [false, false, null]; - } - - let lines = text.split('\n'); - let [mime, action, ...files] = lines; - - if (mime != 'x-special/nautilus-clipboard') { - return [false, false, null]; - } - if (!['copy', 'cut'].includes(action)) { - return [false, false, null]; - } - let isCut = action == 'cut'; - - /* Last line is empty due to the split */ - if (files.length <= 1) { - return [false, false, null]; - } - /* Remove last line */ - files.pop(); - - return [true, isCut, files]; - } - - onMotion(x, y) { - if (this.rubberBand) { - this.x1 = Math.min(x, this.rubberBandInitX); - this.x2 = Math.max(x, this.rubberBandInitX); - this.y1 = Math.min(y, this.rubberBandInitY); - this.y2 = Math.max(y, this.rubberBandInitY); - this.selectionRectangle = new Gdk.Rectangle({'x': this.x1, 'y': this.y1, 'width': this.x2 - this.x1, 'height': this.y2 - this.y1}); - for (let grid of this._desktops) { - grid.queue_draw(); - } - for (let item of this._fileList) { - let labelintersect = item.labelRectangle.intersect(this.selectionRectangle)[0]; - let iconintersect = item.iconRectangle.intersect(this.selectionRectangle)[0]; - if (labelintersect || iconintersect) { - item.setSelected(); - item.touchedByRubberband = true; - } else if (item.touchedByRubberband) { - item.unsetSelected(); - } - } - } - return false; - } - - onReleaseButton() { - if (this.rubberBand) { - this.rubberBand = false; - this.selectionRectangle = null; - } - for (let grid of this._desktops) { - grid.queue_draw(); - } - return false; - } - - _startRubberband(x, y) { - this.rubberBandInitX = x; - this.rubberBandInitY = y; - this.rubberBand = true; - for (let item of this._fileList) { - item.touchedByRubberband = false; - } - } - - selected(fileItem, action) { - switch (action) { - case Enums.Selection.ALONE: - if (!fileItem.isSelected) { - for (let item of this._fileList) { - if (item === fileItem) { - item.setSelected(); - } else { - item.unsetSelected(); - } - } - } - break; - case Enums.Selection.WITH_SHIFT: - fileItem.toggleSelected(); - break; - case Enums.Selection.RIGHT_BUTTON: - if (!fileItem.isSelected) { - for (let item of this._fileList) { - if (item === fileItem) { - item.setSelected(); - } else { - item.unsetSelected(); - } - } - } - break; - case Enums.Selection.ENTER: - if (this.rubberBand) { - fileItem.setSelected(); - } - break; - case Enums.Selection.RELEASE: - for (let item of this._fileList) { - if (item === fileItem) { - item.setSelected(); - } else { - item.unsetSelected(); - } - } - break; - } - } - - _removeAllFilesFromGrids() { - for (let fileItem of this._fileList) { - fileItem.removeFromGrid(true); - } - this._fileList = []; - } - - async _updateDesktop() { - if (this._readingDesktopFiles) { - // just notify that the files changed while being read from the disk. - this._desktopFilesChanged = true; - if (this._desktopEnumerateCancellable && !this._forceDraw) { - this._desktopEnumerateCancellable.cancel(); - this._desktopEnumerateCancellable = null; - } - return; - } - - this._readingDesktopFiles = true; - this._forceDraw = false; - this._lastDesktopUpdateRequest = GLib.get_monotonic_time(); - let fileList = []; - /* eslint-disable no-await-in-loop */ - while (true) { - this._desktopFilesChanged = false; - if (!this._desktopDir.query_exists(null)) { - fileList = []; - break; - } - fileList = await this._doReadAsync(); - if (this._forcedExit) { - return; - } - if (fileList !== null) { - if (!this._desktopFilesChanged) { - break; - } - if (this._forceDraw) { - this._drawDesktop(fileList); - this._lastDesktopUpdateRequest = GLib.get_monotonic_time(); - } - } - await DesktopIconsUtil.waitDelayMs(500); - if ((GLib.get_monotonic_time() - this._lastDesktopUpdateRequest) > 1000000) { - this._forceDraw = true; - } else { - this._forceDraw = false; - } - } - this._readingDesktopFiles = false; - this._forceDraw = false; - this._drawDesktop(fileList); - } - - _doReadAsync() { - if (this._desktopEnumerateCancellable) { - this._desktopEnumerateCancellable.cancel(); - } - this._desktopEnumerateCancellable = new Gio.Cancellable(); - return new Promise((resolve, reject) => { - this._desktopDir.enumerate_children_async( - Enums.DEFAULT_ATTRIBUTES, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - this._desktopEnumerateCancellable, - (source, result) => { - this._desktopEnumerateCancellable = null; - try { - let fileEnum = source.enumerate_children_finish(result); - if (this._desktopFilesChanged && !this._forceDraw) { - resolve(null); - return; - } - let fileList = []; - for (let [newFolder, extras] of DesktopIconsUtil.getExtraFolders()) { - try { - fileList.push(new FileItem.FileItem(this, - newFolder, - newFolder.query_info(Enums.DEFAULT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, null), - extras, - null)); - } catch (e) { - print(`Failed with ${e.message} while adding extra folder ${newFolder.get_uri()}\n${e.stack}`); - } - } - let info; - while ((info = fileEnum.next_file(null))) { - let fileItem = new FileItem.FileItem(this, - fileEnum.get_child(info), - info, - Enums.FileType.NONE, - null); - if (fileItem.isHidden && !this._showHidden) { - /* if there are hidden files in the desktop and the user doesn't want to - show them, remove the coordinates. This ensures that if the user enables - showing them, they won't fight with other icons for the same place - */ - if (fileItem.savedCoordinates) { - // only overwrite them if needed - fileItem.savedCoordinates = null; - } - continue; - } - fileList.push(fileItem); - if (fileItem.dropCoordinates == null) { - let basename = fileItem.file.get_basename(); - if (basename in this._pendingDropFiles) { - fileItem.dropCoordinates = this._pendingDropFiles[basename]; - delete this._pendingDropFiles[basename]; - } - } - } - for (let [newFolder, extras, volume] of DesktopIconsUtil.getMounts(this._volumeMonitor)) { - try { - fileList.push(new FileItem.FileItem(this, - newFolder, - newFolder.query_info(Enums.DEFAULT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, null), - extras, - volume)); - } catch (e) { - print(`Failed with ${e} while adding volume ${newFolder}`); - } - } - resolve(fileList); - return; - } catch (e) { - resolve(null); - } - } - ); - }); - } - - _drawDesktop(fileList) { - this._selectedFiles = this.getCurrentSelection(true); - if (this._renameWindow) { - // disconnect the popup from the fileItem to avoid it being - // destroyed when the fileItem is removed from the desktop - this._renameWindow.updateFileItem(null); - } - this._removeAllFilesFromGrids(); - this._fileList = fileList; - // Select the files that were selected before the repaint - if (this._selectedFiles) { - for (let fileItem of fileList) { - if (this._selectedFiles.includes(fileItem.uri)) { - fileItem.setSelected(); - } - } - } - if (this._renameWindow) { - // assign the popover to the new fileItem - let file = fileList.filter(f => f.fileName == this._renamingFile)[0]; - if (file) { - file.setRenamePopup(this._renameWindow); - } else { - this._renameWindow.closeWindow(); - } - } - this._placeAllFilesOnGrids(); - this.fileItemMenu.refreshedIcons(); - this._selectedFiles = null; - } - - _placeAllFilesOnGrids(redisplay = false) { - this.keepStacked = Prefs.desktopSettings.get_boolean('keep-stacked'); - this.keepArranged = Prefs.desktopSettings.get_boolean('keep-arranged'); - this.sortSpecialFolders = Prefs.desktopSettings.get_boolean('sort-special-folders'); - if (this.keepStacked) { - this.doStacks(redisplay); - } else if (this.keepArranged) { - this.doSorts(); - } else { - this._addFilesToDesktop(this._fileList, Enums.StoredCoordinates.PRESERVE); - } - } - - _addFilesToDesktop(fileList, storeMode) { - if (this._desktops.length == 0) { - return; - } - let outOfDesktops = []; - let notAssignedYet = []; - - // First, add those icons that fit in the current desktops - for (let fileItem of fileList) { - if (fileItem.savedCoordinates == null) { - notAssignedYet.push(fileItem); - continue; - } - if (fileItem.dropCoordinates != null) { - fileItem.dropCoordinates = null; - } - let [itemX, itemY] = fileItem.savedCoordinates; - let addedToDesktop = false; - for (let desktop of this._desktops) { - if (desktop.getDistance(itemX, itemY) == 0) { - addedToDesktop = true; - desktop.addFileItemCloseTo(fileItem, itemX, itemY, storeMode); - break; - } - } - if (!addedToDesktop) { - outOfDesktops.push(fileItem); - } - } - // Now, assign those icons that are outside the current desktops, - // but have assigned coordinates - for (let fileItem of outOfDesktops) { - let minDistance = -1; - let [itemX, itemY] = fileItem.savedCoordinates; - let newDesktop = null; - for (let desktop of this._desktops) { - let distance = desktop.getDistance(itemX, itemY); - if (distance == -1) { - continue; - } - if ((minDistance == -1) || (distance < minDistance)) { - minDistance = distance; - newDesktop = desktop; - } - } - if (newDesktop == null) { - print('Not enough space to add icons'); - break; - } else { - newDesktop.addFileItemCloseTo(fileItem, itemX, itemY, storeMode); - } - } - // Finally, assign those icons that still don't have coordinates - for (let fileItem of notAssignedYet) { - let x, y; - if (fileItem.dropCoordinates == null) { - if (this._primaryScreen !== null) { - x = this._primaryScreen.x; - y = this._primaryScreen.y; - } else { - x = 0; - y = 0; - } - storeMode = Enums.StoredCoordinates.ASSIGN; - } else { - [x, y] = fileItem.dropCoordinates; - fileItem.dropCoordinates = null; - storeMode = Enums.StoredCoordinates.OVERWRITE; - } - // try first in the designated desktop - let assigned = false; - for (let desktop of this._desktops) { - if (desktop.getDistance(x, y) == 0) { - desktop.addFileItemCloseTo(fileItem, x, y, storeMode); - assigned = true; - break; - } - } - if (assigned) { - continue; - } - // if there is no space in the designated desktop, try in another - for (let desktop of this._desktops) { - if (desktop.getDistance(x, y) != -1) { - desktop.addFileItemCloseTo(fileItem, x, y, storeMode); - break; - } - } - } - } - - _updateWritableByOthers() { - let info = this._desktopDir.query_info(Gio.FILE_ATTRIBUTE_UNIX_MODE, - Gio.FileQueryInfoFlags.NONE, - null); - this.unixMode = info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE); - let writableByOthers = (this.unixMode & Enums.S_IWOTH) != 0; - if (writableByOthers != this.writableByOthers) { - this.writableByOthers = writableByOthers; - if (this.writableByOthers) { - print('desktop-icons: Desktop is writable by others - will not allow launching any desktop files'); - } - return true; - } else { - return false; - } - } - - _updateDesktopIfChanged(file, otherFile, eventType) { - if (eventType == Gio.FileMonitorEvent.CHANGED) { - // use only CHANGES_DONE_HINT - return; - } - if (!this._showHidden && (file.get_basename()[0] == '.')) { - // If the file is not visible, we don't need to refresh the desktop - // Unless it is a hidden file being renamed to visible - if (!otherFile || (otherFile.get_basename()[0] == '.')) { - return; - } - } - switch (eventType) { - case Gio.FileMonitorEvent.MOVED_IN: - case Gio.FileMonitorEvent.MOVED_CREATED: - /* Remove the coordinates that could exist to avoid conflicts between - files that are already in the desktop and the new one - */ - try { - let info = new Gio.FileInfo(); - info.set_attribute_string('metadata::nautilus-icon-position', ''); - file.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) {} // can happen if a file is created and deleted very fast - break; - case Gio.FileMonitorEvent.ATTRIBUTE_CHANGED: - /* The desktop is what changed, and not a file inside it */ - if (file.get_uri() == this._desktopDir.get_uri()) { - if (this._updateWritableByOthers()) { - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop from Directory Monitor Attribute Change: ${e.message}\n${e.stack}`); - }); - } - return; - } - break; - } - this._updateDesktop().catch(e => { - print(`Exception while updating Desktop from Directory Monitor: ${e.message}\n${e.stack}`); - }); - } - - _getClipboardText() { - let selection = this.getCurrentSelection(true); - if (selection) { - return new GLib.Variant('as', selection); - } else { - return new GLib.Variant('as', []); - } - } - - /* - * Due to a problem in the Clipboard API in Gtk3, it is not possible to do the CUT/COPY operation from - * dynamic languages like Javascript, because one of the methods needed is marked as NOT INTROSPECTABLE - * - * https://discourse.gnome.org/t/missing-gtk-clipboard-set-with-data-in-gtk-3/6920 - * - * The right solution is to migrate DING to Gtk4, where the whole API is available, but that is a very - * big task, so in the meantime, we take advantage of the fact that the St API, in Gnome Shell, can put - * binary contents in the clipboard, so we use DBus to notify that we want to do a CUT or a COPY operation, - * passing the URIs as parameters, and delegate that to the DING Gnome Shell extension. This is easily done - * with a GLib.SimpleAction. - */ - doCopy() { - DBusUtils.extensionControl.activate_action('doCopy', this._getClipboardText()); - } - - doCut() { - DBusUtils.extensionControl.activate_action('doCut', this._getClipboardText()); - } - - doTrash() { - const selection = this._fileList.filter(i => i.isSelected && !i.isSpecial).map(i => - i.file.get_uri()); - - if (selection.length) { - DBusUtils.RemoteFileOperations.TrashURIsRemote(selection); - } - } - - doDeletePermanently() { - const toDelete = this._fileList.filter(i => i.isSelected && !i.isSpecial).map(i => - i.file.get_uri()); - - if (!toDelete.length) { - if (this._fileList.some(i => i.isSelected && i.isTrash)) { - this.doEmptyTrash(); - } - return; - } - - DBusUtils.RemoteFileOperations.DeleteURIsRemote(toDelete); - } - - doEmptyTrash(askConfirmation = true) { - DBusUtils.RemoteFileOperations.EmptyTrashRemote(askConfirmation); - } - - checkIfSpecialFilesAreSelected() { - for (let item of this._fileList) { - if (item.isSelected && item.isSpecial) { - return true; - } - } - return false; - } - - checkIfDirectoryIsSelected() { - for (let item of this._fileList) { - if (item.isSelected && item.isDirectory) { - return true; - } - } - return false; - } - - getCurrentSelection(getUri) { - let listToTrash = []; - for (let fileItem of this._fileList) { - if (fileItem.isSelected) { - if (getUri) { - listToTrash.push(fileItem.file.get_uri()); - } else { - listToTrash.push(fileItem); - } - } - } - if (listToTrash.length != 0) { - return listToTrash; - } else { - return null; - } - } - - getNumberOfSelectedItems() { - let count = 0; - for (let item of this._fileList) { - if (item.isSelected) { - count++; - } - } - return count; - } - - getFileItemFromURI(uri) { - for (let item of this._fileList) { - if (uri == item.uri) { - return item; - } - } - return null; - } - - doRename(fileItem, allowReturnOnSameName) { - if (!fileItem || !fileItem.canRename) { - return; - } - this.unselectAll(); - if (!this._renameWindow) { - this._renamingFile = fileItem.fileName; - this._renameWindow = new AskRenamePopup.AskRenamePopup(fileItem, allowReturnOnSameName, () => { - this._renameWindow = null; - this.newFolderDoRename = null; - this._renamingFile = null; - }); - } - } - - fileExistsOnDesktop(searchName) { - const listOfFileNamesOnDesktop = this.updateFileList().map(f => f.fileName); - if (listOfFileNamesOnDesktop.includes(searchName)) { - return true; - } else { - return false; - } - } - - getDesktopUniqueFileName(fileName) { - let fileParts = DesktopIconsUtil.getFileExtensionOffset(fileName); - let i = 0; - let newName = fileName; - - while (this.fileExistsOnDesktop(newName)) { - i += 1; - newName = `${fileParts.basename} ${i}${fileParts.extension}`; - } - return newName; - } - - doNewFolder(position = null, suggestedName = null, opts = {rename: true}) { - this.unselectAll(); - - if (!position) { - position = [this._clickX, this._clickY]; - } - - const baseName = suggestedName ? suggestedName : _('New Folder'); - let newName = this.getDesktopUniqueFileName(baseName); - - if (newName) { - let dir = DesktopIconsUtil.getDesktopDir().get_child(newName); - try { - dir.make_directory(null); - const info = new Gio.FileInfo(); - info.set_attribute_string('metadata::nautilus-drop-position', `${position.join(',')}`); - info.set_attribute_string('metadata::nautilus-icon-position', ''); - dir.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) { - logError(e, 'Failed to create folder'); - const header = _('Folder Creation Failed'); - const text = _('Error while trying to create a Folder'); - this.dbusManager.doNotify(header, text); - if (position || suggestedName) { - return null; - } - return null; - } - if (opts.rename) { - this.newFolderDoRename = newName; - } - if (position || suggestedName) { - return dir.get_uri(); - } - } - return null; - } - - _newDocument(template) { - const file = Gio.File.new_for_path(template); - if ((file == null) || !file.query_exists(null)) { - return; - } - - const fullName = file.get_basename(); - const finalName = this.getDesktopUniqueFileName(fullName); - - let destination = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP), finalName])); - - try { - file.copy(destination, Gio.FileCopyFlags.NONE, null, null); - const info = new Gio.FileInfo(); - info.set_attribute_string('metadata::nautilus-drop-position', `${this._clickX},${this._clickY}`); - info.set_attribute_string('metadata::nautilus-icon-position', ''); - destination.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) { - logError(e, `Failed to create template ${e.message}`); - const header = _('Template Creation Failed'); - const text = _('Error while trying to create a Document'); - this.dbusManager.doNotify(header, text); - } - } - - _addSortingMenu() { - this._menu.add(new Gtk.SeparatorMenuItem()); - - this._cleanUpMenuItem = new Gtk.MenuItem({label: _('Arrange Icons')}); - this._cleanUpMenuItem.connect('activate', () => this._sortAllFilesFromGridsByPosition()); - this._menu.add(this._cleanUpMenuItem); - - this._ArrangeByMenuItem = new Gtk.MenuItem({label: _('Arrange By...')}); - this._menu.add(this._ArrangeByMenuItem); - this._addSortingSubMenu(); - } - - _addSortingSubMenu() { - this._arrangeSubMenu = new Gtk.Menu(); - this._ArrangeByMenuItem.set_submenu(this._arrangeSubMenu); - - this._keepArrangedMenuItem = new Gtk.CheckMenuItem({label: _('Keep Arranged...')}); - Prefs.desktopSettings.bind('keep-arranged', this._keepArrangedMenuItem, 'active', 3); - this._arrangeSubMenu.add(this._keepArrangedMenuItem); - - this._keepStackedMenuItem = new Gtk.CheckMenuItem({label: _('Keep Stacked by type...')}); - Prefs.desktopSettings.bind('keep-stacked', this._keepStackedMenuItem, 'active', 3); - this._arrangeSubMenu.add(this._keepStackedMenuItem); - this._keepArrangedMenuItem.bind_property('active', this._cleanUpMenuItem, 'sensitive', 6); - - this._sortSpecialFilesMenuItem = new Gtk.CheckMenuItem({label: _('Sort Home/Drives/Trash...')}); - Prefs.desktopSettings.bind('sort-special-folders', this._sortSpecialFilesMenuItem, 'active', 3); - this._arrangeSubMenu.add(this._sortSpecialFilesMenuItem); - - this._arrangeSubMenu.add(new Gtk.SeparatorMenuItem()); - - this._radioName = new Gtk.RadioMenuItem({label: _('Sort by Name')}); - this._arrangeSubMenu.add(this._radioName); - this._radioDescName = new Gtk.RadioMenuItem({label: _('Sort by Name Descending')}); - this._radioDescName.join_group(this._radioName); - this._arrangeSubMenu.add(this._radioDescName); - this._radioTimeName = new Gtk.RadioMenuItem({label: _('Sort by Modified Time')}); - this._radioTimeName.join_group(this._radioName); - this._arrangeSubMenu.add(this._radioTimeName); - this._radioKindName = new Gtk.RadioMenuItem({label: _('Sort by Type')}); - this._radioKindName.join_group(this._radioName); - this._arrangeSubMenu.add(this._radioKindName); - this._radioSizeName = new Gtk.RadioMenuItem({label: _('Sort by Size')}); - this._radioSizeName.join_group(this._radioName); - this._arrangeSubMenu.add(this._radioSizeName); - this.doArrangeRadioButtons(); - this._radioName.connect('activate', () => { - this.setIfActive(this._radioName, Enums.SortOrder.NAME); - }); - this._radioDescName.connect('activate', () => { - this.setIfActive(this._radioDescName, Enums.SortOrder.DESCENDINGNAME); - }); - this._radioTimeName.connect('activate', () => { - this.setIfActive(this._radioTimeName, Enums.SortOrder.MODIFIEDTIME); - }); - this._radioKindName.connect('activate', () => { - this.setIfActive(this._radioKindName, Enums.SortOrder.KIND); - }); - this._radioSizeName.connect('activate', () => { - this.setIfActive(this._radioSizeName, Enums.SortOrder.SIZE); - }); - - this._arrangeSubMenu.show_all(); - } - - onToggleStackUnstackThisTypeClicked(type, typeInList, unstackList) { - if (!unstackList) { - unstackList = Prefs.getUnstackList(); - typeInList = unstackList.includes(type); - } - if (typeInList) { - let index = unstackList.indexOf(type); - unstackList.splice(index, 1); - } else { - unstackList.push(type); - } - Prefs.setUnstackList(unstackList); - } - - doStacks(restack) { - if (restack) { - for (let fileItem of this._fileList) { - fileItem.removeFromGrid(false); - } - } - if (!this.stackInitialCoordinates && !this._allFileList) { - this._allFileList = []; - this._saveStackInitialCoordinates(); - this._keepArrangedMenuItem.hide(); - this._cleanUpMenuItem.hide(); - restack = false; - } - this._sortAllFilesFromGridsByKindStacked(restack); - this._reassignFilesToDesktop(); - } - - _unstack() { - if (this.stackInitialCoordinates && this._allFileList) { - this._fileList.forEach(f => f.removeFromGrid(false)); - this._restoreStackInitialCoordinates(); - this._fileList = this._allFileList; - this._allFileList = null; - this._keepArrangedMenuItem.show(); - this._cleanUpMenuItem.show(); - if (this.keepArranged) { - this.doSorts(); - } else { - this._addFilesToDesktop(this._fileList, Enums.StoredCoordinates.PRESERVE); - } - } - } - - _saveStackInitialCoordinates() { - this.stackInitialCoordinates = []; - for (let fileItem of this._fileList) { - this.stackInitialCoordinates.push([fileItem.fileName, fileItem.savedCoordinates]); - } - } - - _restoreStackInitialCoordinates() { - if (this.stackInitialCoordinates && this.stackInitialCoordinates.length != 0) { - this._allFileList.forEach(fileItem => { - this.stackInitialCoordinates.forEach(savedItem => { - if (savedItem[0] == fileItem.fileName) { - fileItem.savedCoordinates = savedItem[1]; - } - }); - }); - } - this.stackInitialCoordinates = null; - } - - _makeStackTopMarkerFolder(type, list) { - let stackAttribute = type.split('/')[1]; - let fileItem = new stackItem.stackItem( - this, - stackAttribute, - type, - Enums.FileType.STACK_TOP - ); - list.push(fileItem); - } - - _sortAllFilesFromGridsByKindStacked(restack) { - /** - * - */ - function determineStackTopSizeOrTime() { - for (let item of otherFiles) { - if (item.isStackMarker) { - for (let unstackitem of stackedFiles) { - if (item.attributeContentType == unstackitem.attributeContentType) { - item.size = unstackitem.fileSize; - item.time = unstackitem.modifiedTime; - break; - } - } - } - } - } - - let specialFiles = []; - let directoryFiles = []; - let validDesktopFiles = []; - let otherFiles = []; - let stackedFiles = []; - let newFileList = []; - let stackTopMarkerFolderList = []; - let unstackList = Prefs.getUnstackList(); - if (this._allFileList && restack) { - this._fileList = this._allFileList; - } - this._sortByName(this._fileList); - for (let fileItem of this._fileList) { - if (fileItem.isSpecial) { - specialFiles.push(fileItem); - continue; - } - if (fileItem.isDirectory) { - directoryFiles.push(fileItem); - continue; - } - if (fileItem._isValidDesktopFile) { - validDesktopFiles.push(fileItem); - continue; - } else { - let type = fileItem.attributeContentType; - let stacked = false; - for (let item of otherFiles) { - if (type == item.attributeContentType) { - stackedFiles.push(fileItem); - stacked = true; - } - } - if (!stacked) { - fileItem.isStackTop = true; - otherFiles.push(fileItem); - } - continue; - } - } - for (let a of otherFiles) { - let instack = false; - for (let c of stackedFiles) { - if (c.attributeContentType == a.attributeContentType) { - instack = true; - break; - } - } - if (!instack) { - a.stackUnique = true; - } - continue; - } - for (let item of otherFiles) { - if (!item.stackUnique) { - this._makeStackTopMarkerFolder(item.attributeContentType, stackTopMarkerFolderList); - item.isStackTop = false; - stackedFiles.push(item); - } - if (item.stackUnique) { - stackTopMarkerFolderList.push(item); - } - item.updateIcon().catch(e => { - print(`Exception while updating an icon: ${e.message}\n${e.stack}`); - }); - } - otherFiles = []; - this._sortByName(specialFiles); - this._sortByName(directoryFiles); - this._sortByName(validDesktopFiles); - this._sortByKindByName(stackedFiles); - this._sortByKindByName(stackTopMarkerFolderList); - otherFiles.push(...specialFiles); - otherFiles.push(...validDesktopFiles); - otherFiles.push(...directoryFiles); - otherFiles.push(...stackTopMarkerFolderList); - /** - * - * @param a - * @param b - */ - function bySize(a, b) { - return a.fileSize - b.fileSize; - } - /** - * - * @param a - * @param b - */ - function byTime(a, b) { - return a._modifiedTime - b._modifiedTime; - } - switch (Prefs.getSortOrder()) { - case Enums.SortOrder.NAME: - this._sortByName(otherFiles); - break; - case Enums.SortOrder.DESCENDINGNAME: - this._sortByName(otherFiles); - otherFiles.reverse(); - this._sortByName(stackedFiles); - stackedFiles.reverse(); - break; - case Enums.SortOrder.MODIFIEDTIME: - - stackedFiles.sort(byTime); - determineStackTopSizeOrTime(); - otherFiles.sort(byTime); - break; - case Enums.SortOrder.KIND: - break; - case Enums.SortOrder.SIZE: - stackedFiles.sort(bySize); - determineStackTopSizeOrTime(); - otherFiles.sort(bySize); - break; - default: - break; - } - for (let item of otherFiles) { - newFileList.push(item); - let itemtype = item.attributeContentType; - for (let unstackitem of stackedFiles) { - if (unstackList.includes(unstackitem.attributeContentType) && (unstackitem.attributeContentType == itemtype)) { - newFileList.push(unstackitem); - } - } - } - if (this._allFileList) { - this._allFileList = this._fileList; - } - this._fileList = newFileList; - } - - setIfActive(buttonname, choice) { - if (buttonname.get_active()) { - Prefs.setSortOrder(choice); - } - } - - _sortByName(fileList) { - /** - * - * @param a - * @param b - */ - function byName(a, b) { - // sort by label name instead of the the fileName or displayName so that the "Home" folder is sorted in the correct order - // alphabetical sort taking into account accent characters & locale, natural language sort for numbers, ie 10.etc before 2.etc - // other options for locale are best fit, or by specifying directly in function below for translators - return a._label.get_text().localeCompare(b._label.get_text(), {sensitivity: 'accent', numeric: 'true', localeMatcher: 'lookup'}); - } - fileList.sort(byName); - } - - _sortByKindByName(fileList) { - /** - * - * @param a - * @param b - */ - function byKindByName(a, b) { - return a.attributeContentType.localeCompare(b.attributeContentType) || - a._label.get_text().localeCompare(b._label.get_text(), {sensitivity: 'accent', numeric: 'true', localeMatcher: 'lookup'}); - } - fileList.sort(byKindByName); - } - - _sortAllFilesFromGridsByName(order) { - this._sortByName(this._fileList); - if (order == Enums.SortOrder.DESCENDINGNAME) { - this._fileList.reverse(); - } - this._reassignFilesToDesktop(); - } - - _sortAllFilesFromGridsByPosition() { - if (this.keepArranged) { - return; - } - this._fileList.map(f => f.removeFromGrid(false)); - let cornerInversion = Prefs.get_start_corner(); - if (!cornerInversion[0] && !cornerInversion[1]) { - this._fileList.sort((a, b) => { - if (a._x1 < b._x1) { - return -1; - } - if (a._x1 > b._x1) { - return 1; - } - if (a._y1 < b._y1) { - return -1; - } - if (a._y1 > b._y1) { - return 1; - } - return 0; - }); - } - if (cornerInversion[0] && cornerInversion[1]) { - this._fileList.sort((a, b) => { - if (a._x1 < b._x1) { - return 1; - } - if (a._x1 > b._x1) { - return -1; - } - if (a._y1 < b._y1) { - return 1; - } - if (a._y1 > b._y1) { - return -1; - } - return 0; - }); - } - if (cornerInversion[0] && !cornerInversion[1]) { - this._fileList.sort((a, b) => { - if (a._x1 < b._x1) { - return 1; - } - if (a._x1 > b._x1) { - return -1; - } - if (a._y1 < b._y1) { - return -1; - } - if (a._y1 > b._y1) { - return 1; - } - return 0; - }); - } - if (!cornerInversion[0] && cornerInversion[1]) { - this._fileList.sort((a, b) => { - if (a._x1 < b._x1) { - return -1; - } - if (a._x1 > b._x1) { - return 1; - } - if (a._y1 < b._y1) { - return 1; - } - if (a._y1 > b._y1) { - return -1; - } - return 0; - }); - } - this._reassignFilesToDesktop(); - } - - _sortAllFilesFromGridsByModifiedTime() { - /** - * - * @param a - * @param b - */ - function byTime(a, b) { - return a._modifiedTime - b._modifiedTime; - } - this._fileList.sort(byTime); - this._reassignFilesToDesktop(); - } - - _sortAllFilesFromGridsBySize() { - /** - * - * @param a - * @param b - */ - function bySize(a, b) { - return a.fileSize - b.fileSize; - } - this._fileList.sort(bySize); - this._reassignFilesToDesktop(); - } - - _sortAllFilesFromGridsByKind() { - let specialFiles = []; - let directoryFiles = []; - let validDesktopFiles = []; - let otherFiles = []; - let newFileList = []; - for (let fileItem of this._fileList) { - if (fileItem._isSpecial) { - specialFiles.push(fileItem); - continue; - } - if (fileItem._isDirectory) { - directoryFiles.push(fileItem); - continue; - } - if (fileItem._isValidDesktopFile) { - validDesktopFiles.push(fileItem); - continue; - } else { - otherFiles.push(fileItem); - continue; - } - } - this._sortByName(specialFiles); - this._sortByName(directoryFiles); - this._sortByName(validDesktopFiles); - this._sortByKindByName(otherFiles); - newFileList.push(...specialFiles); - newFileList.push(...validDesktopFiles); - newFileList.push(...directoryFiles); - newFileList.push(...otherFiles); - if (this._fileList.length == newFileList.length) { - this._fileList = newFileList; - } - this._reassignFilesToDesktop(); - } - - _reassignFilesToDesktop() { - if (!this.sortSpecialFolders) { - this._reassignFilesToDesktopPreserveSpecialFiles(); - return; - } - for (let fileItem of this._fileList) { - fileItem.savedCoordinates = null; - fileItem.dropCoordinates = null; - } - this._addFilesToDesktop(this._fileList, Enums.StoredCoordinates.ASSIGN); - } - - _reassignFilesToDesktopPreserveSpecialFiles() { - let specialFiles = []; - let otherFiles = []; - let newFileList = []; - for (let fileItem of this._fileList) { - if (fileItem._isSpecial) { - specialFiles.push(fileItem); - continue; - } - if (!fileItem._isSpecial) { - otherFiles.push(fileItem); - fileItem.savedCoordinates = null; - fileItem.dropCoordinates = null; - continue; - } - } - newFileList.push(...specialFiles); - newFileList.push(...otherFiles); - if (this._fileList.length == newFileList.length) { - this._fileList = newFileList; - } - this._addFilesToDesktop(this._fileList, Enums.StoredCoordinates.PRESERVE); - } - - doArrangeRadioButtons() { - switch (Prefs.getSortOrder()) { - case Enums.SortOrder.NAME: - this._radioName.set_active(true); - break; - case Enums.SortOrder.DESCENDINGNAME: - this._radioDescName.set_active(true); - break; - case Enums.SortOrder.MODIFIEDTIME: - this._radioTimeName.set_active(true); - break; - case Enums.SortOrder.KIND: - this._radioKindName.set_active(true); - break; - case Enums.SortOrder.SIZE: - this._radioSizeName.set_active(true); - break; - default: - this._radioName.set_active(true); - Prefs.setSortOrder(Enums.SortOrder.NAME); - break; - } - } - - doSorts(cleargrids) { - if (cleargrids) { - this._fileList.map(f => f.removeFromGrid(false)); - } - switch (Prefs.getSortOrder()) { - case Enums.SortOrder.NAME: - this._sortAllFilesFromGridsByName(); - break; - case Enums.SortOrder.DESCENDINGNAME: - this._sortAllFilesFromGridsByName(Enums.SortOrder.DESCENDINGNAME); - break; - case Enums.SortOrder.MODIFIEDTIME: - this._sortAllFilesFromGridsByModifiedTime(); - break; - case Enums.SortOrder.KIND: - this._sortAllFilesFromGridsByKind(); - break; - case Enums.SortOrder.SIZE: - this._sortAllFilesFromGridsBySize(); - break; - default: - this._addFilesToDesktop(this._fileList, Enums.StoredCoordinates.PRESERVE); - break; - } - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/ding.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/ding.js deleted file mode 100755 index 9a1550a..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/ding.js +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/env gjs - -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -imports.gi.versions.Gtk = '3.0'; -const Gtk = imports.gi.Gtk; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; - -let desktops = []; -let lastCommand = null; -let codePath = '.'; -let errorFound = false; -let asDesktop = false; -let primaryIndex = 0; - -/** - * - */ -function printUsage() { - print('Desktop Icons NG'); - print('Usage:'); - print(' -h : show this help'); - print(' -E : run as desktop (with transparent window, reading data from the extension...)'); - print(' -P code path : set the path where the code is stored'); - print(' -M index : index of the primary monitor'); - print(' -D x:y:w:h:z:t:b:l:r:i : monitor data'); - print(' x: X coordinate'); - print(' y: Y coordinate'); - print(' w: width in pixels'); - print(' h: height in pixels'); - print(' z: zoom value (must be greater than or equal to one)'); - print(' t: top margin in pixels'); - print(' b: bottom margin in pixels'); - print(' l: left margin in pixels'); - print(' r: right margin in pixels'); - print(' i: monitor index (0, 1...)'); -} - -/** - * - * @param argv - */ -function parseCommandLine(argv) { - desktops = []; - let data; - for (let arg of argv) { - if (lastCommand == null) { - switch (arg) { - case '-h': - case '-H': - printUsage(); - errorFound = true; - break; - case '-E': - // run it as a true desktop (transparent window and so on) - asDesktop = true; - break; - case '-P': // Code path - case '-D': // Desktop definition: X:Y:WIDTH:HEIGHT:ZOOM:MARGINTOP:MARGINBOTTOM:MARGINLEFT:MARGINRIGHT:MONITORINDEX - case '-M': // Primary monitor - lastCommand = arg; - break; - default: - print(`Parameter ${arg} not recognized. Aborting.`); - errorFound = true; - break; - } - continue; - } - if (errorFound) { - break; - } - switch (lastCommand) { - case '-P': - codePath = arg; - break; - case '-D': - data = arg.split(':'); - if (data.length != 10) { - print('Incorrect number of parameters for -D\n'); - printUsage(); - errorFound = true; - break; - } - if (parseFloat(data[4]) < 1.0) { - print("Error: ZOOM value can't be less than one\n"); - printUsage(); - errorFound = true; - break; - } - desktops.push({ - x: parseInt(data[0]), - y: parseInt(data[1]), - width: parseInt(data[2]), - height: parseInt(data[3]), - zoom: parseFloat(data[4]), - marginTop: parseInt(data[5]), - marginBottom: parseInt(data[6]), - marginLeft: parseInt(data[7]), - marginRight: parseInt(data[8]), - monitorIndex: parseInt(data[9]), - }); - break; - case '-M': - primaryIndex = parseInt(arg); - break; - } - lastCommand = null; - } - if ((desktops.length == 0) && !asDesktop) { - /* if no desktop list is provided, like when launching the program in stand-alone mode, - * configure a 1280x720 desktop - */ - desktops.push({x: 0, y: 0, width: 1280, height: 720, zoom: 1, marginTop: 0, marginBottom: 0, marginLeft: 0, marginRight: 0, monitorIndex: 0}); - } - for (let desktop of desktops) { - desktop.primaryMonitor = primaryIndex; - } -} - -parseCommandLine(ARGV); - -// this allows to import files from the current folder - -imports.searchPath.unshift(codePath); - -const DBusUtils = imports.dbusUtils; -const Prefs = imports.preferences; -const Gettext = imports.gettext; -const PromiseUtils = imports.promiseUtils; - -PromiseUtils._promisify({keepOriginal: true}, Gio.FileEnumerator.prototype, 'close_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio.FileEnumerator.prototype, 'next_files_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio._LocalFilePrototype, 'delete_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio._LocalFilePrototype, 'enumerate_children_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio._LocalFilePrototype, 'make_directory_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio._LocalFilePrototype, 'query_info_async'); -PromiseUtils._promisify({keepOriginal: true}, Gio._LocalFilePrototype, 'set_attributes_async'); - -let localePath = GLib.build_filenamev([codePath, '..', 'locale']); -if (Gio.File.new_for_path(localePath).query_exists(null)) { - Gettext.bindtextdomain('ding', localePath); -} - -const DesktopManager = imports.desktopManager; - -var desktopManager = null; -var dbusManager = null; - -// Use different AppIDs to allow to test it from a command line while the main desktop is also running from the extension -const dingApp = new Gtk.Application({ - application_id: asDesktop ? 'com.rastersoft.ding' : 'com.rastersoft.dingtest', - flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE | Gio.ApplicationFlags.REPLACE, -}); - -dingApp.connect('startup', () => { - Prefs.init(codePath); - dbusManager = DBusUtils.init(); -}); - -dingApp.connect('activate', () => { - if (!desktopManager) { - desktopManager = new DesktopManager.DesktopManager(dingApp, - dbusManager, - desktops, - codePath, - asDesktop, - primaryIndex); - } -}); - -dingApp.connect('command-line', (app, commandLine) => { - let argv = []; - argv = commandLine.get_arguments(); - parseCommandLine(argv); - if (!errorFound) { - if (commandLine.get_is_remote()) { - desktopManager.updateGridWindows(desktops); - } else { - dingApp.activate(); - } - commandLine.set_exit_status(0); - } else { - commandLine.set_exit_status(1); - } -}); - -if (!errorFound) { - dingApp.run(ARGV); -} - -if (!errorFound) { - 0; -} else { - 1; -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/enums.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/enums.js deleted file mode 100644 index 50551af..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/enums.js +++ /dev/null @@ -1,109 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -var ICON_SIZE = {'tiny': 36, 'small': 48, 'standard': 64, 'large': 96}; -var ICON_WIDTH = {'tiny': 70, 'small': 90, 'standard': 120, 'large': 130}; -var ICON_HEIGHT = {'tiny': 80, 'small': 90, 'standard': 106, 'large': 138}; - -var START_CORNER = { - 'top-left': [false, false], - 'top-right': [true, false], - 'bottom-left': [false, true], - 'bottom-right': [true, true], -}; - -var FileType = { - NONE: null, - USER_DIRECTORY_HOME: 'show-home', - USER_DIRECTORY_TRASH: 'show-trash', - EXTERNAL_DRIVE: 'external-drive', - STACK_TOP: 'stack-top', -}; - -var StoredCoordinates = { - PRESERVE: 0, - OVERWRITE: 1, - ASSIGN: 2, -}; - -var Selection = { - ALONE: 0, - WITH_SHIFT: 1, - RIGHT_BUTTON: 2, - ENTER: 3, - LEAVE: 4, - RELEASE: 5, -}; - -/* From NautilusFileUndoManagerState */ -var UndoStatus = { - NONE: 0, - UNDO: 1, - REDO: 2, -}; - -var FileExistOperation = { - ASK: 0, - OVERWRITE: 1, - RENAME: 2, - SKIP: 3, -}; - -var WhatToDoWithExecutable = { - EXECUTE: 0, - EXECUTE_IN_TERMINAL: 1, - DISPLAY: 2, - CANCEL: 3, -}; - -var SortOrder = { - ORDER: 'arrangeorder', - NAME: 'name', - DESCENDINGNAME: 'descendingname', - MODIFIEDTIME: 'modifiedtime', - KIND: 'kind', - SIZE: 'size', -}; - -var CompressionType = { - ZIP: 0, - TAR_XZ: 1, - SEVEN_ZIP: 2, - ENCRYPTED_ZIP: 3, -}; - -var DndTargetInfo = { - DING_ICON_LIST: 0, - GNOME_ICON_LIST: 1, - URI_LIST: 2, - TEXT_PLAIN: 3, -}; - -var DEFAULT_ATTRIBUTES = 'metadata::*,standard::*,access::*,time::modified,unix::mode'; -var TERMINAL_SCHEMA = 'org.gnome.desktop.default-applications.terminal'; -var SCHEMA_NAUTILUS = 'org.gnome.nautilus.preferences'; -var SCHEMA_NAUTILUS_COMPRESSION = 'org.gnome.nautilus.compression'; -var SCHEMA_GTK = 'org.gtk.Settings.FileChooser'; -var SCHEMA = 'org.gnome.shell.extensions.ding'; -var SCHEMA_MUTTER = 'org.gnome.mutter'; -var EXEC_KEY = 'exec'; -var NAUTILUS_SCRIPTS_DIR = '.local/share/nautilus/scripts'; -var SCHEMA_DARK_SETTINGS = 'org.gnome.desktop.interface'; - -var S_IXUSR = 0o00100; -var S_IWOTH = 0o00002; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItem.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItem.js deleted file mode 100644 index 13435ec..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItem.js +++ /dev/null @@ -1,796 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * SwitcherooControl code based on code original from Marsch84 - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; -const DesktopIconsUtil = imports.desktopIconsUtil; -const desktopIconItem = imports.desktopIconItem; -const ShowErrorPopup = imports.showErrorPopup; - -const Prefs = imports.preferences; -const Enums = imports.enums; -const DBusUtils = imports.dbusUtils; - -const Signals = imports.signals; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var FileItem = class extends desktopIconItem.desktopIconItem { - constructor(desktopManager, file, fileInfo, fileExtra, custom) { - super(desktopManager, fileExtra); - this._fileInfo = fileInfo; - this._custom = custom; - this._isSpecial = this._fileExtra != Enums.FileType.NONE; - this._file = file; - this.isStackTop = false; - this.stackUnique = false; - this._realizeId = 0; - - this._savedCoordinates = this._readCoordinatesFromAttribute(fileInfo, 'metadata::nautilus-icon-position'); - this._dropCoordinates = this._readCoordinatesFromAttribute(fileInfo, 'metadata::nautilus-drop-position'); - - this._createIconActor(); - this._setFileName(this._getVisibleName()); - - /* Set the metadata and update relevant UI */ - this._updateMetadataFromFileInfo(fileInfo); - - this._updateIcon().catch(e => { - print(`Exception while updating an icon: ${e.message}\n${e.stack}`); - }); - - if (this._attributeCanExecute && !this._isValidDesktopFile) { - this._execLine = this.file.get_path(); - } else { - this._execLine = null; - } - if (fileExtra == Enums.FileType.USER_DIRECTORY_TRASH) { - // if this icon is the trash, monitor the state of the directory to update the icon - this._trashChanged = false; - this._queryTrashInfoCancellable = null; - this._scheduleTrashRefreshId = 0; - this._monitorTrashDir = this._file.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); - this._monitorTrashId = this._monitorTrashDir.connect('changed', (obj, file, otherFile, eventType) => { - switch (eventType) { - case Gio.FileMonitorEvent.DELETED: - case Gio.FileMonitorEvent.MOVED_OUT: - case Gio.FileMonitorEvent.CREATED: - case Gio.FileMonitorEvent.MOVED_IN: - if (this._queryTrashInfoCancellable || this._scheduleTrashRefreshId) { - if (this._scheduleTrashRefreshId) { - GLib.source_remove(this._scheduleTrashRefreshId); - } - if (this._queryTrashInfoCancellable) { - this._queryTrashInfoCancellable.cancel(); - this._queryTrashInfoCancellable = null; - } - this._scheduleTrashRefreshId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { - this._refreshTrashIcon(); - this._scheduleTrashRefreshId = 0; - return GLib.SOURCE_REMOVE; - }); - } else { - this._refreshTrashIcon(); - // after a refresh, don't allow more refreshes until 200ms after, to coalesce extra events - this._scheduleTrashRefreshId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { - this._scheduleTrashRefreshId = 0; - return GLib.SOURCE_REMOVE; - }); - } - break; - } - }); - } else { - this._monitorTrashId = 0; - } - this._updateName(); - if (this._dropCoordinates) { - this.setSelected(); - } - } - - setRenamePopup(renameWindow) { - if (this._realizeId) { - this.container.disconnect(this._realizeId); - } - this._realizeId = this.container.connect_after('realize', () => { - renameWindow.updateFileItem(this); - this.container.disconnect(this._realizeId); - this._realizeId = 0; - }); - } - - /** ********************* - * Destroyers * - ***********************/ - - _destroy() { - /* Trash */ - if (this._monitorTrashId) { - this._monitorTrashDir.disconnect(this._monitorTrashId); - this._monitorTrashDir.cancel(); - this._monitorTrashId = 0; - } - if (this._queryTrashInfoCancellable) { - this._queryTrashInfoCancellable.cancel(); - } - if (this._scheduleTrashRefreshId) { - GLib.source_remove(this._scheduleTrashRefreshId); - this._scheduleTrashRefreshId = 0; - } - /* Metadata */ - if (this._setMetadataTrustedCancellable) { - this._setMetadataTrustedCancellable.cancel(); - } - if (this._realizeId && this.container) { - this.container.disconnect(this._realizeId); - this._realizeId = 0; - } - // call super() after disconnecting everything, because it destroys - // the top widget, and that will destroy also all the other widgets. - super._destroy(); - } - - /** ********************* - * Creators * - ***********************/ - - _getVisibleName(useAttributes) { - if (this._fileExtra == Enums.FileType.EXTERNAL_DRIVE) { - return this._custom.get_name(); - } else { - return this._fileInfo.get_display_name(); - } - } - - _setFileName(text) { - if (this._fileExtra == Enums.FileType.USER_DIRECTORY_HOME) { - // TRANSLATORS: "Home" is the text that will be shown in the user's personal folder - text = _('Home'); - } - this._setLabelName(text); - } - - _readCoordinatesFromAttribute(fileInfo, attribute) { - let savedCoordinates = fileInfo.get_attribute_as_string(attribute); - if ((savedCoordinates != null) && (savedCoordinates != '')) { - savedCoordinates = savedCoordinates.split(','); - if (savedCoordinates.length >= 2) { - if (!isNaN(savedCoordinates[0]) && !isNaN(savedCoordinates[1])) { - return [Number(savedCoordinates[0]), Number(savedCoordinates[1])]; - } - } - } - return null; - } - - _doLabelSizeAllocated() { - super._doLabelSizeAllocated(); - this._checkForRename(); - } - - _checkForRename() { - if (this._desktopManager.newFolderDoRename) { - if (this._desktopManager.newFolderDoRename == this.fileName) { - this._desktopManager.doRename(this, true); - } - } - } - - _refreshMetadataAsync(rebuild) { - if (this._destroyed) { - return; - } - - if (this._queryFileInfoCancellable) { - this._queryFileInfoCancellable.cancel(); - } - this._queryFileInfoCancellable = new Gio.Cancellable(); - this._file.query_info_async(Enums.DEFAULT_ATTRIBUTES, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - this._queryFileInfoCancellable, - (source, result) => { - try { - this._queryFileInfoCancellable = null; - let newFileInfo = source.query_info_finish(result); - this._updateMetadataFromFileInfo(newFileInfo); - newFileInfo = undefined; - if (rebuild) { - this._updateIcon().catch(e => { - print(`Exception while updating the icon after a metadata update: ${e.message}\n${e.stack}`); - }); - } - this._updateName(); - } catch (error) { - if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - print(`Error getting the file info: ${error}`); - } - } - } - ); - } - - _updateMetadataFromFileInfo(fileInfo) { - this._fileInfo = fileInfo; - - let oldLabelText = this._currentFileName; - - this._displayName = this._getVisibleName(); - this._attributeCanExecute = fileInfo.get_attribute_boolean('access::can-execute'); - this._unixmode = fileInfo.get_attribute_uint32('unix::mode'); - this._writableByOthers = (this._unixmode & Enums.S_IWOTH) != 0; - this._trusted = fileInfo.get_attribute_as_string('metadata::trusted') == 'true'; - this._attributeContentType = fileInfo.get_content_type(); - this._isDesktopFile = this._attributeContentType == 'application/x-desktop'; - - if (this._isDesktopFile && this._writableByOthers) { - log(`desktop-icons: File ${this._displayName} is writable by others - will not allow launching`); - } - - if (this._isDesktopFile) { - try { - this._desktopFile = Gio.DesktopAppInfo.new_from_filename(this._file.get_path()); - if (!this._desktopFile) { - log(`Couldn’t parse ${this._displayName} as a desktop file, will treat it as a regular file.`); - this._isValidDesktopFile = false; - } else { - this._isValidDesktopFile = true; - } - } catch (e) { - print(`Error reading Desktop file ${this.uri}: ${e}`); - } - } else { - this._isValidDesktopFile = false; - } - - if (this.displayName != oldLabelText) { - this._setFileName(this.displayName); - } - - this._fileType = fileInfo.get_file_type(); - this._isDirectory = this._fileType == Gio.FileType.DIRECTORY; - this._isSpecial = this._fileExtra != Enums.FileType.NONE; - this._isHidden = fileInfo.get_is_hidden() | fileInfo.get_is_backup(); - this._isSymlink = fileInfo.get_is_symlink(); - this._modifiedTime = fileInfo.get_attribute_uint64('time::modified'); - /* - * This is a glib trick to detect broken symlinks. If a file is a symlink, the filetype - * points to the final file, unless it is broken; thus if the file type is SYMBOLIC_LINK, - * it must be a broken link. - * https://developer.gnome.org/gio/stable/GFile.html#g-file-query-info - */ - this._isBrokenSymlink = this._isSymlink && this._fileType == Gio.FileType.SYMBOLIC_LINK; - } - - _doOpenContext(context, fileList) { - if (!fileList) { - fileList = []; - } - if (this._isBrokenSymlink) { - log(`Error: Can’t open ${this.file.get_uri()} because it is a broken symlink.`); - let title = _('Broken Link'); - let error = _('Can not open this File because it is a Broken Symlink'); - this._showerrorpopup(title, error); - return; - } - - if (this._isDesktopFile) { - this._launchDesktopFile(context, fileList); - return; - } - - if (this._isDirectory && this._desktopManager.useNemo) { - try { - DesktopIconsUtil.trySpawn(GLib.get_home_dir(), ['nemo', this.file.get_uri()], DesktopIconsUtil.getFilteredEnviron()); - } catch (err) { - log(`Error trying to launch Nemo: ${err.message}\n${err}`); - } - return; - } - - if (!DBusUtils.GnomeArchiveManager.isAvailable && - this._fileType === Gio.FileType.REGULAR && - this._desktopManager.autoAr.fileIsCompressed(this.fileName)) { - this._desktopManager.autoAr.extractFile(this.fileName); - return; - } - Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(), - null, null, - (source, result) => { - try { - Gio.AppInfo.launch_default_for_uri_finish(result); - } catch (e) { - log(`Error opening file ${this.file.get_uri()}: ${e.message}`); - } - } - ); - } - - _showerrorpopup(title, error) { - new ShowErrorPopup.ShowErrorPopup( - title, - error, - true - ); - } - - _launchDesktopFile(context, fileList) { - if (this.trustedDesktopFile) { - this._desktopFile.launch_uris_as_manager(fileList, context, GLib.SpawnFlags.SEARCH_PATH, null, null); - return; - } - - let error; - - if (!this._isValidDesktopFile) { - let title = _('Broken Desktop File'); - let error = _('This .desktop file has errors or points to a program without permissions. It can not be executed.\n\n\tEdit the file to set the correct executable Program.'); - this._showerrorpopup(title, error); - return; - } - - if (this._writableByOthers || !this._attributeCanExecute) { - let title = _('Invalid Permissions on Desktop File'); - let error = _('This .desktop File has incorrect Permissions. Right Click to edit Properties, then:\n'); - if (this._writableByOthers) { - error += _('\nSet Permissions, in "Others Access", "Read Only" or "None"'); - } - if (!this._attributeCanExecute) { - error += _('\nEnable option, "Allow Executing File as a Program"'); - } - this._showerrorpopup(title, error); - return; - } - - if (!this.trustedDesktopFile) { - let title = 'Untrusted Desktop File'; - let error = _('This .desktop file is not trusted, it can not be launched. To enable launching, right-click, then:\n\nEnable "Allow Launching"'); - this._showerrorpopup(title, error); - } - } - - _updateName() { - if (this._isValidDesktopFile && !this._desktopManager.writableByOthers && !this._writableByOthers && this.trustedDesktopFile) { - this._setFileName(this._desktopFile.get_locale_string('Name')); - } else { - this._setFileName(this._getVisibleName()); - } - } - - /** ********************* - * Button Clicks * - ***********************/ - - _doButtonOnePressed(event, shiftPressed, controlPressed) { - super._doButtonOnePressed(event, shiftPressed, controlPressed); - if (this.getClickCount() == 2 && !Prefs.CLICK_POLICY_SINGLE) { - this.doOpen(); - } - } - - _doButtonOneReleased(event) { - // primaryButtonPressed is TRUE only if the user has pressed the button - // over an icon, and if (s)he has not started a drag&drop operation - if (this._primaryButtonPressed) { - this._primaryButtonPressed = false; - let shiftPressed = !!(event.get_state()[1] & Gdk.ModifierType.SHIFT_MASK); - let controlPressed = !!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK); - if (!shiftPressed && !controlPressed) { - this._desktopManager.selected(this, Enums.Selection.RELEASE); - if (Prefs.CLICK_POLICY_SINGLE) { - this.doOpen(); - } - } - } - } - - /** ********************* - * Drag and Drop * - ***********************/ - - _setDropDestination(dropDestination) { - dropDestination.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP, null, - Gdk.DragAction.MOVE | Gdk.DragAction.COPY | Gdk.DragAction.DEFAULT); - if ((this._fileExtra == Enums.FileType.USER_DIRECTORY_TRASH) || - (this._fileExtra == Enums.FileType.USER_DIRECTORY_HOME) || - (this._fileExtra != Enums.FileType.EXTERNAL_DRIVE) || - this._isDirectory) { - let targets = new Gtk.TargetList(null); - targets.add(Gdk.atom_intern('x-special/gnome-icon-list', false), 0, 1); - targets.add(Gdk.atom_intern('text/uri-list', false), 0, 2); - dropDestination.drag_dest_set_target_list(targets); - targets = undefined; - this._connectSignal(dropDestination, 'drag-data-received', (widget, context, x, y, selection, info, time) => { - const forceCopy = context.get_selected_action() === Gdk.DragAction.COPY; - if (info === Enums.DndTargetInfo.GNOME_ICON_LIST || - info === Enums.DndTargetInfo.URI_LIST) { - let fileList = DesktopIconsUtil.getFilesFromNautilusDnD(selection, info); - if (fileList.length != 0) { - if (this._hasToRouteDragToGrid()) { - this._grid.receiveDrop(context, this._x1 + x, this._y1 + y, selection, info, true, forceCopy); - return; - } - if (this._desktopManager.dragItem && ((this._desktopManager.dragItem.uri == this._file.get_uri()) || !(this._isValidDesktopFile || this.isDirectory))) { - // Dragging a file/folder over itself or over another file will do nothing, allow drag to directory or validdesktop file - Gtk.drag_finish(context, false, false, time); - return; - } - if (this._isValidDesktopFile) { - // open the desktopfile with these dropped files as the arguments - this.doOpen(fileList); - Gtk.drag_finish(context, true, false, time); - return; - } - if (this._fileExtra != Enums.FileType.USER_DIRECTORY_TRASH) { - let data = Gio.File.new_for_uri(fileList[0]).query_info('id::filesystem', Gio.FileQueryInfoFlags.NONE, null); - let idFS = data.get_attribute_string('id::filesystem'); - if ((this._desktopManager.desktopFsId == idFS) && !forceCopy) { - DBusUtils.RemoteFileOperations.MoveURIsRemote(fileList, this._file.get_uri()); - Gtk.drag_finish(context, true, true, time); - } else { - DBusUtils.RemoteFileOperations.CopyURIsRemote(fileList, this._file.get_uri()); - Gtk.drag_finish(context, true, false, time); - } - } else { - DBusUtils.RemoteFileOperations.TrashURIsRemote(fileList); - Gtk.drag_finish(context, true, true, time); - } - } - } else { - Gtk.drag_finish(context, false, false, time); - } - }); - } - } - - _hasToRouteDragToGrid() { - return this._isSelected && (this._desktopManager.dragItem !== null) && (this._desktopManager.dragItem.uri !== this._file.get_uri()); - } - - /** ********************* - * Icon Rendering * - ***********************/ - - _refreshTrashIcon() { - if (this._queryTrashInfoCancellable) { - this._queryTrashInfoCancellable.cancel(); - this._queryTrashInfoCancellable = null; - } - if (!this._file.query_exists(null)) { - return false; - } - this._queryTrashInfoCancellable = new Gio.Cancellable(); - - this._file.query_info_async(Enums.DEFAULT_ATTRIBUTES, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - this._queryTrashInfoCancellable, - (source, result) => { - try { - this._queryTrashInfoCancellable = null; - this._fileInfo = source.query_info_finish(result); - this._updateIcon().catch(e => { - print(`Exception while updating the trash icon: ${e.message}\n${e.stack}`); - }); - } catch (error) { - if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - print(`Error getting the number of files in the trash: ${error.message}\n${error.stack}`); - } - } - }); - return false; - } - - - /** ********************* - * Class Methods * - ***********************/ - - onAttributeChanged() { - if (this._destroyed) { - return; - } - if (this._isDesktopFile) { - this._refreshMetadataAsync(true); - } - } - - updatedMetadata() { - this._refreshMetadataAsync(true); - } - - onFileRenamed(file) { - this._file = file; - this._refreshMetadataAsync(false); - } - - eject() { - if (this._custom) { - this._custom.eject_with_operation(Gio.MountUnmountFlags.NONE, null, null, (obj, res) => { - obj.eject_with_operation_finish(res); - }); - } - } - - unmount() { - if (this._custom) { - this._custom.unmount_with_operation(Gio.MountUnmountFlags.NONE, null, null, (obj, res) => { - obj.unmount_with_operation_finish(res); - }); - } - } - - doOpen(fileList) { - if (!fileList) { - fileList = []; - } - this._doOpenContext(null, fileList); - } - - onAllowDisallowLaunchingClicked() { - this.metadataTrusted = !this.trustedDesktopFile; - - /* - * we're marking as trusted, make the file executable too. Note that we - * do not ever remove the executable bit, since we don't know who set - * it. - */ - if (this.metadataTrusted && !this._attributeCanExecute) { - let info = new Gio.FileInfo(); - let newUnixMode = this._unixmode | Enums.S_IXUSR; - info.set_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE, newUnixMode); - this._file.set_attributes_async(info, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_LOW, - null, - (source, result) => { - try { - source.set_attributes_finish(result); - } catch (error) { - log(`Failed to set execution flag: ${error.message}`); - } - }); - } - this._updateName(); - } - - doDiscreteGpu() { - if (!DBusUtils.discreteGpuAvailable) { - log('Could not apply discrete GPU environment, switcheroo-control not available'); - return; - } - let gpus = DBusUtils.SwitcherooControl.proxy.GPUs; - if (!gpus) { - log('Could not apply discrete GPU environment. No GPUs in list.'); - return; - } - - for (let gpu in gpus) { - if (!gpus[gpu]) { - continue; - } - - let default_variant = gpus[gpu]['Default']; - if (!default_variant || default_variant.get_boolean()) { - continue; - } - - let env = gpus[gpu]['Environment']; - if (!env) { - continue; - } - - let envS = env.get_strv(); - let context = new Gio.AppLaunchContext(); - for (let i = 0; i < envS.length; i += 2) { - context.setenv(envS[i], envS[i + 1]); - } - this._doOpenContext(context, null); - return; - } - log('Could not find discrete GPU data in switcheroo-control'); - } - - _onOpenTerminalClicked() { - DesktopIconsUtil.launchTerminal(this.file.get_path(), null); - } - - /** ********************* - * Getters and setters * - ***********************/ - - get attributeContentType() { - return this._attributeContentType; - } - - get attributeCanExecute() { - return this._attributeCanExecute; - } - - get canEject() { - if (this._custom) { - return this._custom.can_eject(); - } else { - return false; - } - } - - get canRename() { - return !this.trustedDesktopFile && (this._fileExtra == Enums.FileType.NONE); - } - - get canUnmount() { - if (this._custom) { - return this._custom.can_unmount(); - } else { - return false; - } - } - - get displayName() { - if (this.trustedDesktopFile) { - return this._desktopFile.get_name(); - } - return this._displayName || null; - } - - get dropCoordinates() { - return this._dropCoordinates; - } - - set dropCoordinates(pos) { - try { - let info = new Gio.FileInfo(); - if (pos != null) { - this._dropCoordinates = [pos[0], pos[1]]; - info.set_attribute_string('metadata::nautilus-drop-position', `${pos[0]},${pos[1]}`); - } else { - this._dropCoordinates = null; - info.set_attribute_string('metadata::nautilus-drop-position', ''); - } - this.file.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) { - print(`Failed to store the desktop coordinates for ${this.uri}: ${e}`); - } - } - - get execLine() { - return this._execLine; - } - - get file() { - return this._file; - } - - get fileName() { - return this._fileInfo.get_name(); - } - - get fileSize() { - return this._fileInfo.get_size(); - } - - get isAllSelectable() { - return this._fileExtra == Enums.FileType.NONE; - } - - get isDirectory() { - return this._isDirectory; - } - - get isHidden() { - return this._isHidden; - } - - get isTrash() { - return this._fileExtra === Enums.FileType.USER_DIRECTORY_TRASH; - } - - get metadataTrusted() { - return this._trusted; - } - - set metadataTrusted(value) { - this._trusted = value; - - if (this._setMetadataTrustedCancellable) { - this._setMetadataTrustedCancellable.cancel(); - } - this._setMetadataTrustedCancellable = new Gio.Cancellable(); - let info = new Gio.FileInfo(); - info.set_attribute_string('metadata::trusted', - value ? 'true' : 'false'); - this._file.set_attributes_async(info, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_LOW, - this._setMetadataTrustedCancellable, - (source, result) => { - try { - this._setMetadataTrustedCancellable = null; - source.set_attributes_finish(result); - this._refreshMetadataAsync(true); - } catch (error) { - if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - log(`Failed to set metadata::trusted: ${error.message}`); - } - } - }); - } - - get modifiedTime() { - return this._modifiedTime; - } - - get path() { - return this._file.get_path(); - } - - get savedCoordinates() { - return this._savedCoordinates; - } - - set savedCoordinates(pos) { - try { - let info = new Gio.FileInfo(); - if (pos != null) { - this._savedCoordinates = [pos[0], pos[1]]; - info.set_attribute_string('metadata::nautilus-icon-position', `${pos[0]},${pos[1]}`); - } else { - this._savedCoordinates = null; - info.set_attribute_string('metadata::nautilus-icon-position', ''); - } - this.file.set_attributes_from_info(info, Gio.FileQueryInfoFlags.NONE, null); - } catch (e) { - print(`Failed to store the desktop coordinates for ${this.uri}: ${e}`); - } - } - - get trustedDesktopFile() { - return this._isValidDesktopFile && - this._attributeCanExecute && - this.metadataTrusted && - !this._desktopManager.writableByOthers && - !this._writableByOthers; - } - - get uri() { - return this._file.get_uri(); - } - - get isValidDesktopFile() { - return this._isValidDesktopFile; - } - - get writableByOthers() { - return this._writableByOthers; - } - - get isStackMarker() { - if (this.isStackTop && !this.stackUnique) { - return true; - } else { - return false; - } - } -}; -Signals.addSignalMethods(FileItem.prototype); diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItemMenu.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItemMenu.js deleted file mode 100644 index e4a1640..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileItemMenu.js +++ /dev/null @@ -1,545 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const DBusUtils = imports.dbusUtils; -const GLib = imports.gi.GLib; -const Gdk = imports.gi.Gdk; -const Gtk = imports.gi.Gtk; -const Gio = imports.gi.Gio; - -const TemplatesScriptsManager = imports.templatesScriptsManager; -const DesktopIconsUtil = imports.desktopIconsUtil; -const Prefs = imports.preferences; -const ShowErrorPopup = imports.showErrorPopup; - -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var FileItemMenu = class { - constructor(desktopManager) { - this._currentFileItem = null; - this._menu = null; - this._desktopManager = desktopManager; - DBusUtils.GnomeArchiveManager.connect('changed-status', () => { - // wait a second to ensure that everything has settled - GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => { - this._getExtractionSupportedTypes(); - return false; - }); - }); - this._askedSupportedTypes = false; - this._scriptsMonitor = new TemplatesScriptsManager.TemplatesScriptsManager( - DesktopIconsUtil.getScriptsDir(), - TemplatesScriptsManager.TemplatesScriptsManagerFlags.ONLY_EXECUTABLE, - this._onScriptClicked.bind(this)); - } - - _getExtractionSupportedTypes() { - this._decompressibleTypes = []; - try { - if (DBusUtils.GnomeArchiveManager.isAvailable) { - DBusUtils.GnomeArchiveManager.proxy.GetSupportedTypesRemote('extract', - (result, error) => { - if (error) { - logError(error, "Can't get the extractable types; ensure that File-Roller is installed.\n"); - return; - } - for (let key of result.values()) { - for (let type of key.values()) { - this._decompressibleTypes.push(Object.values(type)[0]); - } - } - } - ); - } - this._askedSupportedTypes = true; - } catch (e) { - logError(e, 'Error while getting supported types.'); - } - } - - _onScriptClicked(menuItemPath) { - let pathList = 'NAUTILUS_SCRIPT_SELECTED_FILE_PATHS='; - let uriList = 'NAUTILUS_SCRIPT_SELECTED_URIS='; - let currentUri = `NAUTILUS_SCRIPT_CURRENT_URI=${DesktopIconsUtil.getDesktopDir().get_uri()}`; - let params = [menuItemPath]; - for (let item of this._desktopManager.getCurrentSelection(false)) { - if (!item.isSpecial) { - pathList += `${item.file.get_path()}\n`; - uriList += `${item.file.get_uri()}\n`; - params.push(item.file.get_path()); - } - } - - let environ = DesktopIconsUtil.getFilteredEnviron(); - environ.push(pathList); - environ.push(uriList); - environ.push(currentUri); - DesktopIconsUtil.trySpawn(null, params, environ); - } - - refreshedIcons() { - if (!this._menu) { - return; - } - this._currentFileItem = this._desktopManager.getFileItemFromURI(this._currentFileItem.uri); - if (!this._currentFileItem) { - this._menu.destroy(); - this._menu = null; - } - } - - _addSeparator() { - this._menu.add(new Gtk.SeparatorMenuItem()); - } - - _addElementToMenu(label, action = null) { - let element = new Gtk.MenuItem({label}); - this._menu.add(element); - if (action) { - element.connect('activate', action); - } - return element; - } - - showMenu(fileItem, event, atWidget = false) { - if (!this._askedSupportedTypes) { - this._getExtractionSupportedTypes(); - } - this._currentFileItem = fileItem; - - let selectedItemsNum = this._desktopManager.getNumberOfSelectedItems(); - - this._menu = new Gtk.Menu(); - const menuStyleContext = this._menu.get_style_context(); - menuStyleContext.add_class('desktopmenu'); - menuStyleContext.add_class('fileitemmenu'); - - if (!fileItem.isStackMarker) { - this._addElementToMenu( - selectedItemsNum > 1 ? _('Open All...') : _('Open'), - this._doMultiOpen.bind(this) - ); - } - - this._menu.connect_after('selection-done', () => { - this._menu.destroy(); - this._menu = null; - }); - - let keepStacked = Prefs.desktopSettings.get_boolean('keep-stacked'); - if (keepStacked && !fileItem.stackUnique) { - if (!fileItem.isSpecial && !fileItem.isDirectory && !fileItem.isValidDesktopFile) { - let unstackList = Prefs.getUnstackList(); - let typeInList = unstackList.includes(fileItem.attributeContentType); - this._addElementToMenu( - typeInList ? _('Stack This Type') : _('Unstack This Type'), - () => { - this._desktopManager.onToggleStackUnstackThisTypeClicked(this._currentFileItem.attributeContentType, typeInList, unstackList); - } - ); - } - } - - // fileExtra == NONE - - if (fileItem.isAllSelectable && !fileItem.isStackMarker) { - let submenu = this._scriptsMonitor.createMenu(); - if (submenu !== null) { - this._addElementToMenu(_('Scripts')).set_submenu(submenu); - this._addSeparator(); - } - - if (!fileItem.isDirectory) { - this._addElementToMenu( - selectedItemsNum > 1 ? _('Open All With Other Application...') : _('Open With Other Application'), - this._doOpenWith.bind(this) - ).set_sensitive(selectedItemsNum > 0); - - if (DBusUtils.discreteGpuAvailable && fileItem.trustedDesktopFile && (selectedItemsNum == 1)) { - this._addElementToMenu( - _('Launch using Dedicated Graphics Card'), - () => { - this._currentFileItem.doDiscreteGpu(); - } - ); - } - } - - this._addSeparator(); - - if (fileItem.attributeCanExecute && !fileItem.isDirectory && !fileItem.isValidDesktopFile && fileItem.execLine && Gio.content_type_can_be_executable(fileItem.attributeContentType)) { - let execLine = fileItem.execLine; - this._addElementToMenu(_('Run as a program'), () => { - DesktopIconsUtil.spawnCommandLine(`"${execLine}"`); - }); - this._addSeparator(); - } - - let allowCutCopyTrash = this._desktopManager.checkIfSpecialFilesAreSelected(); - this._addElementToMenu( - _('Cut'), - () => { - this._desktopManager.doCut(); - } - ).set_sensitive(!allowCutCopyTrash); - - this._addElementToMenu( - _('Copy'), - () => { - this._desktopManager.doCopy(); - } - ).set_sensitive(!allowCutCopyTrash); - - if (fileItem.canRename && (selectedItemsNum == 1)) { - this._addElementToMenu( - _('Rename…'), - () => { - this._desktopManager.doRename(this._currentFileItem, false); - } - ); - } - - this._addSeparator(); - - this._addElementToMenu( - _('Move to Trash'), - () => { - this._desktopManager.doTrash(); - } - ).set_sensitive(!allowCutCopyTrash); - - if (Prefs.nautilusSettings.get_boolean('show-delete-permanently')) { - this._addElementToMenu( - _('Delete permanently'), - () => { - this._desktopManager.doDeletePermanently(); - } - ).set_sensitive(!allowCutCopyTrash); - } - - if (fileItem.isValidDesktopFile && !this._desktopManager.writableByOthers && !fileItem.writableByOthers && (selectedItemsNum == 1)) { - this._addSeparator(); - this._addElementToMenu( - fileItem.trustedDesktopFile ? _("Don't Allow Launching") : _('Allow Launching'), - () => { - this._currentFileItem.onAllowDisallowLaunchingClicked(); - } - ); - } - } - - // fileExtra == TRASH - - if (fileItem.isTrash) { - this._addSeparator(); - this._addElementToMenu( - _('Empty Trash'), - () => { - this._desktopManager.doEmptyTrash(); - } - ); - } - - // fileExtra == EXTERNAL_DRIVE - - if (fileItem.isDrive) { - this._addSeparator(); - if (fileItem.canEject) { - this._addElementToMenu( - _('Eject'), - () => { - this._currentFileItem.eject(); - } - ); - } - if (fileItem.canUnmount) { - this._addElementToMenu( - _('Unmount'), - () => { - this._currentFileItem.unmount(); - } - ); - } - } - - if (fileItem.isAllSelectable && !this._desktopManager.checkIfSpecialFilesAreSelected() && (selectedItemsNum >= 1)) { - this._addSeparator(); - let addedExtractHere = false; - if (this._getExtractableAutoAr()) { - addedExtractHere = true; - this._addElementToMenu( - _('Extract Here'), - () => this._desktopManager.getCurrentSelection(false).forEach(f => - this._desktopManager.autoAr.extractFile(f.fileName))); - } - if (selectedItemsNum == 1 && this._getExtractable()) { - if (!addedExtractHere) { - this._addElementToMenu( - _('Extract Here'), - () => { - this._extractFileFromSelection(true); - } - ); - } - this._addElementToMenu( - _('Extract To...'), - () => { - this._extractFileFromSelection(false); - } - ); - } - - if (!fileItem.isDirectory) { - this._addElementToMenu( - _('Send to...'), - this._mailFilesFromSelection.bind(this) - ); - } - - if (this._desktopManager.getCurrentSelection().every(f => f.isDirectory)) { - this._addElementToMenu( - Gettext.ngettext( - 'Compress {0} folder', 'Compress {0} folders', selectedItemsNum).replace( - '{0}', selectedItemsNum), - () => this._doCompressFilesFromSelection() - ); - } else { - this._addElementToMenu( - Gettext.ngettext( - 'Compress {0} file', 'Compress {0} files', selectedItemsNum).replace( - '{0}', selectedItemsNum), - () => this._doCompressFilesFromSelection() - ); - } - - - this._addElementToMenu( - Gettext.ngettext('New Folder with {0} item', 'New Folder with {0} items', selectedItemsNum).replace('{0}', selectedItemsNum), - () => { - this._doNewFolderFromSelection(this._currentFileItem); - } - ); - - this._addSeparator(); - } - - if (!fileItem.isStackMarker) { - this._addElementToMenu( - selectedItemsNum > 1 ? _('Common Properties') : _('Properties'), - this._onPropertiesClicked.bind(this) - ); - - this._addSeparator(); - - this._addElementToMenu( - selectedItemsNum > 1 ? _('Show All in Files') : _('Show in Files'), - this._onShowInFilesClicked.bind(this) - ); - } - - if (fileItem.isDirectory && (fileItem.path != null) && (selectedItemsNum == 1)) { - this._addElementToMenu( - _('Open in Terminal'), - () => { - DesktopIconsUtil.launchTerminal(this._currentFileItem.path, null); - } - ); - } - - this._menu.show_all(); - if (atWidget) { - this._menu.popup_at_widget(fileItem.container, Gdk.Gravity.CENTER, Gdk.Gravity.NORTH_WEST, event); - } else { - this._menu.popup_at_pointer(event); - } - } - - _onPropertiesClicked() { - let propertiesFileList = this._desktopManager.getCurrentSelection(true); - const timestamp = Gtk.get_current_event_time(); - DBusUtils.RemoteFileOperations.ShowItemPropertiesRemote(propertiesFileList, timestamp); - } - - _onShowInFilesClicked() { - let showInFilesList = this._desktopManager.getCurrentSelection(true); - if (this._desktopManager.useNemo) { - try { - for (let element of showInFilesList) { - DesktopIconsUtil.trySpawn(GLib.get_home_dir(), ['nemo', element], DesktopIconsUtil.getFilteredEnviron()); - } - return; - } catch (err) { - logError(err, 'Error trying to launch Nemo.'); - } - } - const timestamp = Gtk.get_current_event_time(); - DBusUtils.RemoteFileOperations.ShowItemsRemote(showInFilesList, timestamp); - } - - _doMultiOpen() { - for (let fileItem of this._desktopManager.getCurrentSelection(false)) { - fileItem.unsetSelected(); - fileItem.doOpen(); - } - } - - _doOpenWith() { - let fileItems = this._desktopManager.getCurrentSelection(false); - if (fileItems) { - const context = Gdk.Display.get_default().get_app_launch_context(); - context.set_timestamp(Gtk.get_current_event_time()); - let mimetype = Gio.content_type_guess(fileItems[0].fileName, null)[0]; - let chooser = Gtk.AppChooserDialog.new_for_content_type(null, - Gtk.DialogFlags.MODAL + Gtk.DialogFlags.USE_HEADER_BAR, - mimetype); - chooser.show_all(); - chooser.connect('close', () => { - chooser.response(Gtk.ResponseType.CANCEL); - }); - chooser.connect('response', (actor, retval) => { - if (retval == Gtk.ResponseType.OK) { - let appInfo = chooser.get_app_info(); - if (appInfo) { - let fileList = []; - for (let item of fileItems) { - fileList.push(item.file); - } - appInfo.launch(fileList, context); - } - } - chooser.hide(); - }); - } - } - - _extractFileFromSelection(extractHere) { - let extractFileItemURI; - let extractFolderName; - let position; - const header = _('No Extraction Folder'); - const text = _('Unable to extract File, extraction Folder Does not Exist'); - - for (let fileItem of this._desktopManager.getCurrentSelection(false)) { - extractFileItemURI = fileItem.file.get_uri(); - extractFolderName = fileItem.fileName; - position = fileItem.getCoordinates().slice(0, 2); - fileItem.unsetSelected(); - } - - if (extractHere) { - extractFolderName = DesktopIconsUtil.getFileExtensionOffset(extractFolderName).basename; - const targetURI = this._desktopManager.doNewFolder(position, extractFolderName, {rename: false}); - if (targetURI) { - DBusUtils.RemoteFileOperations.ExtractRemote(extractFileItemURI, targetURI, true); - } else { - this._desktopManager.DBusManager.doNotify(header, text); - } - return; - } - - const dialog = new Gtk.FileChooserDialog({title: _('Select Extract Destination')}); - dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER); - dialog.set_create_folders(true); - dialog.set_current_folder_uri(DesktopIconsUtil.getDesktopDir().get_uri()); - dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - dialog.add_button(_('Select'), Gtk.ResponseType.ACCEPT); - DesktopIconsUtil.windowHidePagerTaskbarModal(dialog, true); - dialog.show_all(); - dialog.connect('close', () => { - dialog.response(Gtk.ResponseType.CANCEL); - }); - dialog.connect('response', (actor, response) => { - if (response === Gtk.ResponseType.ACCEPT) { - const folder = dialog.get_uri(); - if (folder) { - DBusUtils.RemoteFileOperations.ExtractRemote(extractFileItemURI, folder, true); - } else { - this._desktopManager.DBusManager.doNotify(header, text); - } - } - dialog.destroy(); - }); - } - - _getExtractableAutoAr() { - let fileList = this._desktopManager.getCurrentSelection(false); - if (DBusUtils.GnomeArchiveManager.isAvailable && (fileList.length == 1)) { - return false; - } - for (let item of fileList) { - if (!this._desktopManager.autoAr.fileIsCompressed(item.fileName)) { - return false; - } - } - return true; - } - - _getExtractable() { - for (let item of this._desktopManager.getCurrentSelection(false)) { - return this._decompressibleTypes.includes(item.attributeContentType); - } - return false; - } - - _mailFilesFromSelection() { - if (this._desktopManager.checkIfDirectoryIsSelected()) { - let WindowError = new ShowErrorPopup.ShowErrorPopup(_('Can not email a Directory'), - _('Selection includes a Directory, compress the directory to a file first.'), - false); - WindowError.run(); - return; - } - let xdgEmailCommand = []; - xdgEmailCommand.push('xdg-email'); - for (let fileItem of this._desktopManager.getCurrentSelection(false)) { - fileItem.unsetSelected(); - xdgEmailCommand.push('--attach'); - xdgEmailCommand.push(fileItem.file.get_path()); - } - DesktopIconsUtil.trySpawn(null, xdgEmailCommand); - } - - _doCompressFilesFromSelection() { - let desktopFolder = DesktopIconsUtil.getDesktopDir(); - if (desktopFolder) { - if (DBusUtils.GnomeArchiveManager.isAvailable) { - const toCompress = this._desktopManager.getCurrentSelection(true); - DBusUtils.RemoteFileOperations.CompressRemote(toCompress, desktopFolder.get_uri(), true); - } else { - const toCompress = this._desktopManager.getCurrentSelection(false); - this._desktopManager.autoAr.compressFileItems(toCompress, desktopFolder.get_path()); - } - } - this._desktopManager.unselectAll(); - } - - _doNewFolderFromSelection(clickedItem) { - if (!clickedItem) { - return; - } - let position = clickedItem.savedCoordinates; - let newFolderFileItems = this._desktopManager.getCurrentSelection(true); - this._desktopManager.unselectAll(); - clickedItem.removeFromGrid(true); - let newFolder = this._desktopManager.doNewFolder(position); - if (newFolder) { - DBusUtils.RemoteFileOperations.MoveURIsRemote(newFolderFileItems, newFolder); - } - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileUtils.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileUtils.js deleted file mode 100644 index 8951997..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/fileUtils.js +++ /dev/null @@ -1,106 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2022 Marco Trevisan - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const {GLib, Gio} = imports.gi; - -const DEFAULT_ENUMERATE_BATCH_SIZE = 100; -const DEFAULT_QUERY_ATTRIBUTES = [ - Gio.FILE_ATTRIBUTE_STANDARD_NAME, - Gio.FILE_ATTRIBUTE_STANDARD_TYPE, -].join(','); - -/** - * - * @param dir - * @param cancellable - * @param priority - * @param queryAttributes - */ -async function enumerateDir(dir, cancellable = null, priority = GLib.PRIORITY_DEFAULT, - queryAttributes = DEFAULT_QUERY_ATTRIBUTES) { - const childrenEnumerator = await dir.enumerate_children_async_promise(queryAttributes, - Gio.FileQueryInfoFlags.NONE, priority, cancellable); - - try { - const children = []; - while (true) { - // The enumerator doesn't support multiple async calls, nor - // we can predict how many they will be, so using Promise.all - // isn't an option here, thus we just need to await each batch - // eslint-disable-next-line no-await-in-loop - const batch = await childrenEnumerator.next_files_async_promise( - DEFAULT_ENUMERATE_BATCH_SIZE, priority, cancellable); - - if (!batch.length) { - return children; - } - - children.push(...batch); - } - } finally { - if (!childrenEnumerator.is_closed()) { - await childrenEnumerator.close_async_promise(priority, null); - } - } -} - -/** - * - * @param dir - * @param deleteParent - * @param cancellable - * @param priority - */ -async function recursivelyDeleteDir(dir, deleteParent, cancellable = null, - priority = GLib.PRIORITY_DEFAULT) { - const children = await enumerateDir(dir, cancellable, priority); - /* eslint-disable no-await-in-loop */ - for (let info of children) { - await deleteFile(dir.get_child(info.get_name()), info, cancellable, priority); - } - - if (deleteParent) { - await dir.delete_async_promise(priority, cancellable); - } -} - -/** - * - * @param file - * @param info - * @param cancellable - * @param priority - */ -async function deleteFile(file, info = null, cancellable = null, - priority = GLib.PRIORITY_DEFAULT) { - if (!info) { - info = await file.query_info_async_promise( - Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, - priority, cancellable); - } - - const type = info.get_file_type(); - if (type === Gio.FileType.REGULAR || type === Gio.FileType.SYMBOLIC_LINK) { - await file.delete_async_promise(priority, cancellable); - } else if (type === Gio.FileType.DIRECTORY) { - await recursivelyDeleteDir(file, true, cancellable, priority); - } else { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, - `${file.get_path()} of type ${type} cannot be removed`); - } -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/notifyX11UnderWayland.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/notifyX11UnderWayland.js deleted file mode 100644 index 2013f58..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/notifyX11UnderWayland.js +++ /dev/null @@ -1,58 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported NotifyX11UnderWayland */ -'use strict'; -const Gtk = imports.gi.Gtk; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var NotifyX11UnderWayland = class { - constructor(closeCB) { - this._window = new Gtk.MessageDialog({ - window_position: Gtk.WindowPosition.CENTER_ON_PARENT, - transient_for: null, - message_type: Gtk.MessageType.WARNING, - buttons: Gtk.ButtonsType.NONE, - }); - let area = this._window.get_message_area(); - let labels = area.get_children(); - labels[1].set_justify(Gtk.Justification.CENTER); - this._window.secondary_use_markup = true; - this._window.text = _('Desktop Icons NG is running under X11Wayland'); - this._window.secondary_text = _("It seems that you have your system configured to force GTK to use X11. This works, but it's suboptimal. You should check your system configuration to fix this."); - this.deleteButton = this._window.add_button(_('Close'), Gtk.ResponseType.OK); - this.deleteButton.connect('clicked', () => { - this._destroy(closeCB); - }); - this._window.connect('delete-event', () => { - this._destroy(closeCB); - }); - this.deleteButton.get_style_context().add_class('suggested-action'); - this._stopShowing = new Gtk.CheckButton({label: _("Don't show this message anymore.")}); - area.add(this._stopShowing); - this._window.show_all(); - } - - _destroy(closeCB) { - this._window.hide(); - this._window.destroy(); - this._window = null; - closeCB(this._stopShowing.active); - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/preferences.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/preferences.js deleted file mode 100644 index c6517a3..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/preferences.js +++ /dev/null @@ -1,162 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -imports.gi.versions.Gtk = '3.0'; - -const Gtk = imports.gi.Gtk; -const Gio = imports.gi.Gio; -const GioSSS = Gio.SettingsSchemaSource; -const DesktopIconsUtil = imports.desktopIconsUtil; -const Enums = imports.enums; -const PrefsWindow = imports.prefswindow; - -const Gettext = imports.gettext; - -var _ = Gettext.domain('ding').gettext; - -var nautilusSettings; -var nautilusCompression; -var gtkSettings; -var desktopSettings; -var mutterSettings = null; -// This is already in Nautilus settings, so it should not be made tweakable here -var CLICK_POLICY_SINGLE = false; -var prefsWindow; - -var prefsWindow; - -/** - * - * @param path - */ -function init(path) { - let schemaSource = GioSSS.get_default(); - let schemaGtk = schemaSource.lookup(Enums.SCHEMA_GTK, true); - gtkSettings = new Gio.Settings({settings_schema: schemaGtk}); - let schemaObj = schemaSource.lookup(Enums.SCHEMA_NAUTILUS, true); - if (!schemaObj) { - nautilusSettings = null; - } else { - nautilusSettings = new Gio.Settings({settings_schema: schemaObj}); - nautilusSettings.connect('changed', _onNautilusSettingsChanged); - _onNautilusSettingsChanged(); - } - const compressionSchema = schemaSource.lookup(Enums.SCHEMA_NAUTILUS_COMPRESSION, true); - if (!compressionSchema) { - nautilusCompression = null; - } else { - nautilusCompression = new Gio.Settings({settings_schema: compressionSchema}); - } - let schemaDarkSettings = schemaSource.lookup(Enums.SCHEMA_DARK_SETTINGS, true); - if (schemaDarkSettings) { - this.schemaGnomeDarkSettings = new Gio.Settings({ settings_schema: schemaDarkSettings }); - } - - desktopSettings = PrefsWindow.get_schema(path, Enums.SCHEMA); - let schemaMutter = schemaSource.lookup(Enums.SCHEMA_MUTTER, true); - if (schemaMutter) { - mutterSettings = new Gio.Settings({settings_schema: schemaMutter}); - } -} - -/** - * - */ -function showPreferences() { - if (prefsWindow) { - return; - } - prefsWindow = new Gtk.Window({ - resizable: false, - window_position: Gtk.WindowPosition.CENTER, - }); - prefsWindow.connect('destroy', () => { - prefsWindow = null; - }); - prefsWindow.set_title(_('Settings')); - DesktopIconsUtil.windowHidePagerTaskbarModal(prefsWindow, true); - let frame = PrefsWindow.preferencesFrame(Gtk, desktopSettings, nautilusSettings, gtkSettings); - prefsWindow.add(frame); - prefsWindow.show_all(); -} - -/** - * - */ -function _onNautilusSettingsChanged() { - CLICK_POLICY_SINGLE = nautilusSettings.get_string('click-policy') == 'single'; -} - -/** - * - */ -function get_icon_size() { - return Enums.ICON_SIZE[desktopSettings.get_string('icon-size')]; -} - -/** - * - */ -function get_desired_width() { - return Enums.ICON_WIDTH[desktopSettings.get_string('icon-size')]; -} - -/** - * - */ -function get_desired_height() { - return Enums.ICON_HEIGHT[desktopSettings.get_string('icon-size')]; -} - -/** - * - */ -function get_start_corner() { - return Enums.START_CORNER[desktopSettings.get_string('start-corner')].slice(); -} - -/** - * - */ -function getSortOrder() { - return Enums.SortOrder[desktopSettings.get_string(Enums.SortOrder.ORDER)]; -} - -/** - * - * @param order - */ -function setSortOrder(order) { - let x = Object.values(Enums.SortOrder).indexOf(order); - desktopSettings.set_enum(Enums.SortOrder.ORDER, x); -} - -/** - * - */ -function getUnstackList() { - return desktopSettings.get_strv('unstackedtypes'); -} - -/** - * - * @param array - */ -function setUnstackList(array) { - desktopSettings.set_strv('unstackedtypes', array); -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/prefswindow.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/prefswindow.js deleted file mode 100644 index ec17efd..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/prefswindow.js +++ /dev/null @@ -1,215 +0,0 @@ -'use strict'; -const GObject = imports.gi.GObject; -const Gettext = imports.gettext; -const Gio = imports.gi.Gio; -const GioSSS = Gio.SettingsSchemaSource; -const GLib = imports.gi.GLib; - -var _ = Gettext.domain('ding').gettext; - -var Gtk; - -/** - * - * @param path - * @param schema - */ -function get_schema(path, schema) { - // check if this extension was built with "make zip-file", and thus - // has the schema files in a subfolder - // otherwise assume that extension has been installed in the - // same prefix as gnome-shell (and therefore schemas are available - // in the standard folders) - let schemaSource; - let schemaFile = Gio.File.new_for_path(GLib.build_filenamev([path, 'schemas', 'gschemas.compiled'])); - if (schemaFile.query_exists(null)) { - schemaSource = GioSSS.new_from_directory(GLib.build_filenamev([path, 'schemas']), GioSSS.get_default(), false); - } else { - schemaFile = Gio.File.new_for_path(GLib.build_filenamev([path, '..', 'schemas', 'gschemas.compiled'])); - if (schemaFile.query_exists(null)) { - schemaSource = GioSSS.new_from_directory(GLib.build_filenamev([path, '..', 'schemas']), GioSSS.get_default(), false); - } else { - schemaSource = GioSSS.get_default(); - } - } - let schemaObj = schemaSource.lookup(schema, true); - if (!schemaObj) { - throw new Error(`Schema ${schema} could not be found for extension ` + '. Please check your installation.'); - } - - return new Gio.Settings({settings_schema: schemaObj}); -} - -/** - * - * @param _Gtk - * @param desktopSettings - * @param nautilusSettings - * @param gtkSettings - */ -function preferencesFrame(_Gtk, desktopSettings, nautilusSettings, gtkSettings) { - Gtk = _Gtk; - let frame = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 10, - margin_top: 10, - margin_bottom: 10, - margin_start: 10, - margin_end: 10, - }); - if (!frame.add) { - frame.add = frame.append; - } - - frame.add(buildSelector(desktopSettings, 'icon-size', _('Size for the desktop icons'), {'tiny': _('Tiny'), 'small': _('Small'), 'standard': _('Standard'), 'large': _('Large')})); - frame.add(buildSwitcher(desktopSettings, 'show-home', _('Show the personal folder in the desktop'))); - frame.add(buildSwitcher(desktopSettings, 'show-trash', _('Show the trash icon in the desktop'))); - frame.add(buildSwitcher(desktopSettings, 'show-volumes', _('Show external drives in the desktop'))); - frame.add(buildSwitcher(desktopSettings, 'show-network-volumes', _('Show network drives in the desktop'))); - frame.add(buildSelector(desktopSettings, - 'start-corner', - _('New icons alignment'), - { - 'top-left': _('Top-left corner'), - 'top-right': _('Top-right corner'), - 'bottom-left': _('Bottom-left corner'), - 'bottom-right': _('Bottom-right corner'), - })); - frame.add(buildSwitcher(desktopSettings, 'add-volumes-opposite', _('Add new drives to the opposite side of the screen'))); - frame.add(buildSwitcher(desktopSettings, 'show-drop-place', _("Highlight the drop place during Drag'n'Drop"))); - frame.add(buildSwitcher(desktopSettings, 'use-nemo', _('Use Nemo to open folders'))); - - frame.add(buildSwitcher(desktopSettings, 'show-link-emblem', _('Add an emblem to soft links'))); - - frame.add(buildSwitcher(desktopSettings, 'dark-text-in-labels', _('Use dark text in icon labels'))); - - frame.add(new Gtk.Separator({orientation: Gtk.Orientation.HORIZONTAL})); - - - // Nautilus options - let frameLabel = new Gtk.Label({ - label: `${_('Settings shared with Nautilus')}`, - use_markup: true, - }); - let nautilusFrame = new Gtk.Frame({label_widget: frameLabel}); - let nautilusBox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - margin_top: 5, - margin_bottom: 5, - margin_start: 5, - margin_end: 5, - spacing: 10, - }); - if (nautilusFrame.add) { - nautilusFrame.add(nautilusBox); - } else { - nautilusFrame.set_child(nautilusBox); - } - frame.add(nautilusFrame); - - if (!nautilusBox.add) { - nautilusBox.add = nautilusBox.append; - } - nautilusBox.add(buildSelector(nautilusSettings, 'click-policy', _('Click type for open files'), {'single': _('Single click'), 'double': _('Double click')})); - nautilusBox.add(buildSwitcher(gtkSettings, 'show-hidden', _('Show hidden files'))); - nautilusBox.add(buildSwitcher(nautilusSettings, 'show-delete-permanently', _('Show a context menu item to delete permanently'))); - // Gnome Shell 40 removed this option - try { - nautilusBox.add(buildSelector(nautilusSettings, - 'executable-text-activation', - _('Action to do when launching a program from the desktop'), { - 'display': _('Display the content of the file'), - 'launch': _('Launch the file'), - 'ask': _('Ask what to do'), - })); - } catch (e) { - } - nautilusBox.add(buildSelector(nautilusSettings, - 'show-image-thumbnails', - _('Show image thumbnails'), { - 'never': _('Never'), - 'local-only': _('Local files only'), - 'always': _('Always'), - })); - return frame; -} - -/** - * - * @param settings - * @param key - * @param labelText - */ -function buildSwitcher(settings, key, labelText) { - let hbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, spacing: 10}); - let label = new Gtk.Label({label: labelText, xalign: 0}); - if (settings) { - var status = settings.get_boolean(key); - } else { - var status = false; - } - let switcher = new Gtk.Switch({active: status}); - label.set_hexpand(true); - switcher.set_hexpand(false); - switcher.set_halign(Gtk.Align.END); - if (settings) { - settings.bind(key, switcher, 'active', 3); - } else { - switcher.sensitive = false; - } - if (hbox.pack_start) { - hbox.pack_start(label, true, true, 0); - hbox.add(switcher); - } else { - hbox.append(label); - hbox.append(switcher); - } - return hbox; -} - -/** - * - * @param settings - * @param key - * @param labelText - * @param elements - */ -function buildSelector(settings, key, labelText, elements) { - let listStore = new Gtk.ListStore(); - listStore.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]); - if (settings) { - let schemaKey = settings.settings_schema.get_key(key); - let values = schemaKey.get_range().get_child_value(1).get_child_value(0).get_strv(); - for (let val of values) { - let iter = listStore.append(); - let visibleText = val; - if (visibleText in elements) { - visibleText = elements[visibleText]; - } - listStore.set(iter, [0, 1], [visibleText, val]); - } - } - let hbox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL, spacing: 10}); - let label = new Gtk.Label({label: labelText, xalign: 0}); - let combo = new Gtk.ComboBox({model: listStore}); - let rendererText = new Gtk.CellRendererText(); - combo.pack_start(rendererText, false); - combo.add_attribute(rendererText, 'text', 0); - combo.set_id_column(1); - label.set_hexpand(true); - combo.set_hexpand(false); - combo.set_halign(Gtk.Align.END); - if (settings) { - settings.bind(key, combo, 'active-id', 3); - } else { - combo.sensitive = false; - } - if (hbox.pack_start) { - hbox.pack_start(label, true, true, 0); - hbox.add(combo); - } else { - hbox.append(label); - hbox.append(combo); - } - return hbox; -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/promiseUtils.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/promiseUtils.js deleted file mode 100644 index 8e134ca..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/promiseUtils.js +++ /dev/null @@ -1,80 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2022 Marco Trevisan - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -/* This is coming from gjs 1.72, adding options to allow not to replace the - * original method, in case we want to avoid clashes with already used async - * methods. This can be dropped when such requirements are not needed */ -/** - * - * @param options - * @param proto - * @param asyncFunc - * @param finishFunc - */ -function _promisify(options, proto, asyncFunc, - finishFunc = `${asyncFunc.replace(/_(begin|async)$/, '')}_finish`) { - if (proto[asyncFunc] === undefined) { - throw new Error(`${proto} has no method named ${asyncFunc}`); - } - - if (proto[finishFunc] === undefined) { - throw new Error(`${proto} has no method named ${finishFunc}`); - } - - if (proto[`_original_${asyncFunc}`] !== undefined) { - if (options.keepOriginal && proto[`${asyncFunc}_promise`] === undefined) { - proto[`${asyncFunc}_promise`] = proto[asyncFunc]; - } - return; - } - - if (!options) { - options = {}; - } - - proto[`_original_${asyncFunc}`] = proto[asyncFunc]; - proto[options.keepOriginal ? `${asyncFunc}_promise` : asyncFunc] = function (...args) { - if (!args.every(arg => typeof arg !== 'function')) { - return this[`_original_${asyncFunc}`](...args); - } - return new Promise((resolve, reject) => { - const callStack = new Error().stack.split('\n').filter(line => !line.match(/promisify/)).join('\n'); - this[`_original_${asyncFunc}`](...args, (source, res) => { - try { - const result = source !== null && source[finishFunc] !== undefined - ? source[finishFunc](res) - : proto[finishFunc](res); - if (Array.isArray(result) && result.length > 1 && result[0] === true) { - result.shift(); - } - resolve(result); - } catch (error) { - if (error.stack) { - error.stack += `### Promise created here: ###\n${callStack}`; - } else { - error.stack = callStack; - } - reject(error); - } - }); - }); - }; - - if (!options.keepOriginal && proto[`${asyncFunc}_promise`] === undefined) { - proto[`${asyncFunc}_promise`] = proto[asyncFunc]; - } -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/showErrorPopup.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/showErrorPopup.js deleted file mode 100644 index 5a48447..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/showErrorPopup.js +++ /dev/null @@ -1,65 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const Gtk = imports.gi.Gtk; -const DesktopIconsUtil = imports.desktopIconsUtil; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - -var ShowErrorPopup = class { - constructor(text, secondaryText, modal) { - this._window = new Gtk.MessageDialog({ - window_position: Gtk.WindowPosition.CENTER_ON_PARENT, - transient_for: null, - message_type: Gtk.MessageType.ERROR, - buttons: Gtk.ButtonsType.NONE, - }); - let labels = this._window.get_message_area().get_children(); - labels[1].set_justify(Gtk.Justification.CENTER); - this._window.secondary_use_markup = true; - this._window.text = text; - this._window.secondary_text = secondaryText; - DesktopIconsUtil.windowHidePagerTaskbarModal(this._window, true); - this.deleteButton = this._window.add_button(_('Close'), Gtk.ResponseType.OK); - this.deleteButton.connect('clicked', () => { - this._window.hide(); - this._window.destroy(); - this._window = null; - }); - this._window.connect('delete-event', () => { - this._window.destroy(); - this._window = null; - }); - if (modal) { - this._window.show(); - } - } - - run() { - this._window.show(); - this.timeoutClose(3000); - } - - async timeoutClose(time) { - await DesktopIconsUtil.waitDelayMs(time); - if (this._window) { - this.deleteButton.activate(); - } - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stackItem.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stackItem.js deleted file mode 100644 index 5103376..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stackItem.js +++ /dev/null @@ -1,124 +0,0 @@ - -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2021 Sundeep Mediratta (smedius@gmail.com) - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * SwitcherooControl code based on code original from Marsch84 - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const Gdk = imports.gi.Gdk; -const desktopIconItem = imports.desktopIconItem; - -const Prefs = imports.preferences; - -const Signals = imports.signals; -const Gettext = imports.gettext.domain('ding'); - -const _ = Gettext.gettext; - - -var stackItem = class extends desktopIconItem.desktopIconItem { - constructor(desktopManager, file, attributeContentType, fileExtra) { - super(desktopManager, fileExtra); - this._isSpecial = false; - this._file = file; - this.isStackTop = true; - this.stackUnique = false; - this._size = null; - this._modifiedTime = null; - this._attributeContentType = attributeContentType; - this._createIconActor(); - this._createStackTopIcon(); - this._setLabelName(this._file); - } - - _createStackTopIcon() { - const scale = this._icon.get_scale_factor(); - let pixbuf; - let folder = 'folder'; - if (Prefs.getUnstackList().includes(this._attributeContentType)) { - folder = 'folder-open'; - } - pixbuf = this._createEmblemedIcon(null, `${folder}`); - let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); - this._icon.set_from_surface(surface); - } - - _doButtonOnePressed(event, shiftPressed, controlPressed) { - this._desktopManager.onToggleStackUnstackThisTypeClicked(this.attributeContentType); - } - - setSelected() { - - } - - updateIcon() { - this._createStackTopIcon(); - } - - /** ********************* - * Getters and setters * - ***********************/ - - get attributeContentType() { - return this._attributeContentType; - } - - get displayName() { - return this._file; - } - - get file() { - return this._file; - } - - get fileName() { - return this._file; - } - - get fileSize() { - return this._size; - } - - get isAllSelectable() { - return false; - } - - get modifiedTime() { - return this._modifiedTime; - } - - get path() { - return `/tmp/${this._file}`; - } - - get uri() { - return `file:///tmp/${this._file}`; - } - - get isStackMarker() { - return true; - } - - set size(size) { - this._size = size; - } - - set time(time) { - this._modifiedTime = time; - } -}; -Signals.addSignalMethods(stackItem.prototype); diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stylesheet.css b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stylesheet.css deleted file mode 100644 index 4d3e03c..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/stylesheet.css +++ /dev/null @@ -1,30 +0,0 @@ -.file-label, label.file-label:backdrop { - text-shadow: 0px 0px 3px black; - color: white; -} - -.file-label-dark, label.file-label-dark:backdrop { - text-shadow: 0px 0px 3px white; - color: black; -} - -.file-item { - padding: 2px; - border-radius: 5px; -} - -.file-item-hover { - background-color: rgba(238, 238, 238, 0.2); -} - -.not-found { - color: rgb(255, 0, 0); -} - -window.desktopwindow { - background-color: rgba(0, 0, 0, 0); -} - -window.testwindow { - background-color: rgba(0, 0, 0, 100); -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/templatesScriptsManager.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/templatesScriptsManager.js deleted file mode 100644 index 5527cf6..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/templatesScriptsManager.js +++ /dev/null @@ -1,213 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2020 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const Gio = imports.gi.Gio; -const GLib = imports.gi.GLib; -const Gtk = imports.gi.Gtk; -const Enums = imports.enums; -const DesktopIconsUtil = imports.desktopIconsUtil; - -var TemplatesScriptsManagerFlags = { - 'NONE': 0, - 'ONLY_EXECUTABLE': 1, - 'HIDE_EXTENSIONS': 2, -}; - -var TemplatesScriptsManager = class { - constructor(baseFolder, flags, activatedCB) { - this._activatedCB = activatedCB; - this._entries = []; - this._entriesEnumerateCancellable = null; - this._readingEntries = false; - this._entriesDir = baseFolder; - this._entriesDirMonitors = []; - this._entriesFolderChanged = false; - this._flags = flags; - - if (this._entriesDir == GLib.get_home_dir()) { - this._entriesDir = null; - } - if (this._entriesDir !== null) { - this._monitorDir = baseFolder.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); - this._monitorDir.set_rate_limit(1000); - this._monitorDir.connect('changed', (obj, file, otherFile, eventType) => { - this._updateEntries().catch(e => { - print(`Exception while updating entries in monitor: ${e.message}\n${e.stack}`); - }); - }); - this._updateEntries().catch(e => { - print(`Exception while updating entries: ${e.message}\n${e.stack}`); - }); - } - } - - async _updateEntries() { - if (this._readingEntries) { - this._entriesFolderChanged = true; - if (this._entriesEnumerateCancellable) { - this._entriesEnumerateCancellable.cancel(); - this._entriesEnumerateCancellable = null; - } - return; - } - - this._readingEntries = true; - let entriesList = null; - - do { - this._entriesDirMonitors.forEach(f => { - f[0].disconnect(f[1]); - f[0].cancel(); - }); - this._entriesDirMonitors = []; - this._entriesFolderChanged = false; - if (!this._entriesDir.query_exists(null)) { - entriesList = null; - break; - } - entriesList = await this._processDirectory(this._entriesDir); - } while ((entriesList === null) || this._entriesFolderChanged); - - this._entries = entriesList; - this._readingEntries = false; - } - - async _processDirectory(directory) { - if (directory !== this._entriesDir) { - let monitorDir = directory.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); - monitorDir.set_rate_limit(1000); - let monitorId = monitorDir.connect('changed', (obj, file, otherFile, eventType) => { - this._updateEntries(); - }); - this._entriesDirMonitors.push([monitorDir, monitorId]); - } - - try { - var files = await this._readDirectory(directory); - } catch (e) { - return null; - } - - if (files === null) { - return null; - } - let output = []; - for (let file of files) { - if (file[2] === null) { - output.push(file); - continue; - } - file[2] = await this._processDirectory(file[1]); - if (file[2] === null) { - return null; - } - if (file[2].length != 0) { - output.push(file); - } - } - return output; - } - - _readDirectory(directory) { - return new Promise((resolve, reject) => { - if (this._entriesEnumerateCancellable) { - this._entriesEnumerateCancellable.cancel(); - } - this._entriesEnumerateCancellable = new Gio.Cancellable(); - directory.enumerate_children_async( - Enums.DEFAULT_ATTRIBUTES, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - this._entriesEnumerateCancellable, - (source, result) => { - this._entriesEnumerateCancellable = null; - let fileList = []; - try { - let fileEnum = source.enumerate_children_finish(result); - if (this._entriesFolderChanged) { - resolve(null); - return; - } - let info; - while ((info = fileEnum.next_file(null))) { - let isDir = info.get_file_type() == Gio.FileType.DIRECTORY; - if ((this._flags & TemplatesScriptsManagerFlags.ONLY_EXECUTABLE) && - !isDir && - !info.get_attribute_boolean('access::can-execute')) { - continue; - } - let child = fileEnum.get_child(info); - fileList.push([info.get_name(), isDir ? child : child.get_path(), isDir ? [] : null]); - } - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - resolve(null); - } else { - reject(new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.FAILED, - 'file-read-error')); - } - return; - } - fileList.sort((a, b) => { - return a[0].localeCompare(b[0], { - sensitivity: 'accent', - numeric: 'true', - localeMatcher: 'lookup', - }); - }); - resolve(fileList); - } - ); - }); - } - - createMenu() { - return this._createTemplatesScriptsSubMenu(this._entries); - } - - _createTemplatesScriptsSubMenu(scriptsList) { - if ((scriptsList == null) || (scriptsList.length == 0)) { - return null; - } - let scriptSubMenu = new Gtk.Menu(); - for (let fileItem of scriptsList) { - let menuItemName = fileItem[0]; - if (this._flags & TemplatesScriptsManagerFlags.HIDE_EXTENSIONS) { - menuItemName = DesktopIconsUtil.getFileExtensionOffset(menuItemName, false).basename; - } - let menuItemPath = fileItem[1]; - let subDirs = fileItem[2]; - if (subDirs === null) { - let menuItem = new Gtk.MenuItem({label: menuItemName}); - menuItem.connect('activate', () => { - this._activatedCB(menuItemPath); - }); - scriptSubMenu.add(menuItem); - } else { - let subMenu = this._createTemplatesScriptsSubMenu(subDirs); - if (subMenu !== null) { - let menuItem = new Gtk.MenuItem({label: menuItemName}); - menuItem.set_submenu(subMenu); - scriptSubMenu.add(menuItem); - } - } - } - scriptSubMenu.show_all(); - return scriptSubMenu; - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/thumbnails.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/thumbnails.js deleted file mode 100644 index 4b356a2..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/app/thumbnails.js +++ /dev/null @@ -1,178 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -imports.gi.versions.GnomeDesktop = '3.0'; -const GnomeDesktop = imports.gi.GnomeDesktop; -const GLib = imports.gi.GLib; -const Gio = imports.gi.Gio; - -var ThumbnailLoader = class { - constructor(codePath) { - this._timeoutValue = 5000; - this._codePath = codePath; - this._thumbList = []; - this._thumbnailScriptWatch = null; - this._running = false; - this._thumbnailFactoryNormal = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.NORMAL); - this._thumbnailFactoryLarge = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE); - if (this._thumbnailFactoryLarge.generate_thumbnail_async) { - this._useAsyncAPI = true; - print('Detected async api for thumbnails'); - } else { - this._useAsyncAPI = false; - print('Failed to detected async api for thumbnails'); - } - } - - _generateThumbnail(file, callback) { - this._thumbList.push([file, callback]); - if (!this._running) { - this._launchNewBuild(); - } - } - - _launchNewBuild() { - let file, callback; - do { - if (this._thumbList.length == 0) { - this._running = false; - return; - } - // if the file disappeared while waiting in the queue, don't refresh the thumbnail - [file, callback] = this._thumbList.shift(); - if (file.file.query_exists(null)) { - if (this._thumbnailFactoryLarge.has_valid_failed_thumbnail(file.uri, file.modifiedTime)) { - if (callback) { - callback(); - } - continue; - } else { - break; - } - } - } while (true); - this._running = true; - if (this._useAsyncAPI) { - this._createThumbnailAsync(file, callback); - } else { - this._createThumbnailSubprocess(file, callback); - } - } - - _createThumbnailAsync(file, callback) { - let fileInfo = file.file.query_info('standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null); - this._doCancel = new Gio.Cancellable(); - let modifiedTime = fileInfo.get_attribute_uint64('time::modified'); - this._thumbnailFactoryLarge.generate_thumbnail_async(file.uri, fileInfo.get_content_type(), this._doCancel, (obj, res) => { - this._removeTimeout(); - try { - let thumbnailPixbuf = obj.generate_thumbnail_finish(res); - this._thumbnailFactoryLarge.save_thumbnail_async(thumbnailPixbuf, file.uri, modifiedTime, this._doCancel, (obj, res) => { - obj.save_thumbnail_finish(res); - if (callback) { - callback(); - } - this._launchNewBuild(); - }); - } catch (e) { - print(`Error while creating thumbnail: ${e.message}\n${e.stack}`); - this._createFailedThumbnailAsync(file, modifiedTime, callback); - } - }); - this._timeoutID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._timeoutValue, () => { - print(`Timeout while generating thumbnail for ${file.displayName}`); - this._timeoutID = 0; - this._doCancel.cancel(); - this._createFailedThumbnailAsync(file, modifiedTime, callback); - return false; - }); - } - - _createFailedThumbnailAsync(file, modifiedTime, callback) { - this._doCancel = new Gio.Cancellable(); - this._thumbnailFactoryLarge.create_failed_thumbnail_async(file.uri, modifiedTime, this._doCancel, (obj, res) => { - try { - obj.create_failed_thumbnail_finish(res); - } catch (e) { - print(`Error while creating failed thumbnail: ${e.message}\n${e.stack}`); - } - if (callback) { - callback(); - } - this._launchNewBuild(); - }); - } - - _createThumbnailSubprocess(file, callback) { - let args = []; - args.push(GLib.build_filenamev([this._codePath, 'createThumbnail.js'])); - args.push(file.path); - this._proc = new Gio.Subprocess({argv: args}); - this._proc.init(null); - this._proc.wait_check_async(null, (source, result) => { - this._removeTimeout(); - try { - let result2 = source.wait_check_finish(result); - if (result2) { - let status = source.get_status(); - if (status == 0) { - if (callback) { - callback(); - } - } - } else { - print(`Failed to generate thumbnail for ${file.displayName}`); - } - } catch (error) { - print(`Exception when generating thumbnail for ${file.displayName}: ${error}`); - } - this._launchNewBuild(); - }); - this._timeoutID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._timeoutValue, () => { - print(`Timeout while generating thumbnail for ${file.displayName}`); - this._timeoutID = 0; - this._proc.force_exit(); - this._thumbnailFactoryLarge.create_failed_thumbnail(file.uri, file.modifiedTime); - return false; - }); - } - - _removeTimeout() { - if (this._timeoutID != 0) { - GLib.source_remove(this._timeoutID); - this._timeoutID = 0; - } - } - - getThumbnail(file, callback) { - try { - let thumbnail = this._thumbnailFactoryLarge.lookup(file.uri, file.modifiedTime); - if (thumbnail == null) { - thumbnail = this._thumbnailFactoryNormal.lookup(file.uri, file.modifiedTime); - if ((thumbnail == null) && - !this._thumbnailFactoryLarge.has_valid_failed_thumbnail(file.uri, file.modifiedTime) && - this._thumbnailFactoryLarge.can_thumbnail(file.uri, file.attributeContentType, file.modifiedTime)) { - this._generateThumbnail(file, callback); - } - } - return thumbnail; - } catch (error) { - print(`Error when asking for a thumbnail for ${file.displayName}: ${error.message}\n${error.stack}`); - } - return null; - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/emulateX11WindowType.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/emulateX11WindowType.js deleted file mode 100644 index acae59a..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/emulateX11WindowType.js +++ /dev/null @@ -1,376 +0,0 @@ -/* Emulate X11WindowType - * - * Copyright (C) 2020 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported EmulateX11WindowType */ -'use strict'; -import GLib from 'gi://GLib' -import Meta from 'gi://Meta' -import * as Main from 'resource:///org/gnome/shell/ui/main.js' - - -class ManageWindow { - /* This class is added to each managed window, and it's used to - make it behave like an X11 Desktop window. - - Trusted windows will set in the title the characters @!, followed - by the coordinates where to put the window separated by a colon, and - ended in semicolon. After that, it can have one or more of these letters - - * B : put this window at the bottom of the screen - * T : put this window at the top of the screen - * D : show this window in all desktops - * H : hide this window from window list - - Using the title is generally not a problem because the desktop windows - doesn't have a tittle. But some other windows may have and still need to - take advantage of this, so adding a single blank space at the end of the - title is equivalent to @!H, and having two blank spaces at the end of the - title is equivalent to @!HTD. This allows to take advantage of these flags - even to decorated windows. - */ - - constructor(window, waylandClient, changedStatusCB) { - this._waylandClient = waylandClient; - this._window = window; - this._signalIDs = []; - this._changedStatusCB = changedStatusCB; - this._signalIDs.push(window.connect_after('raised', () => { - if (this._keepAtBottom && !this._keepAtTop) { - this._window.lower(); - } - })); - this._signalIDs.push(window.connect('position-changed', () => { - if (this._fixed && (this._x !== null) && (this._y !== null)) { - this._window.move_frame(true, this._x, this._y); - } - })); - this._signalIDs.push(window.connect('notify::title', () => { - this._parseTitle(); - })); - this._signalIDs.push(window.connect('notify::above', () => { - if (this._keepAtBottom && this._window.above) { - this._window.unmake_above(); - } - })); - this._signalIDs.push(window.connect('notify::minimized', () => { - this._window.unminimize(); - })); - this._signalIDs.push(window.connect('notify::maximized-vertically', () => { - if (!window.maximized_vertically) { - window.maximize(Meta.MaximizeFlags.VERTICAL); - } - this._moveIntoPlace(); - })); - this._signalIDs.push(window.connect('notify::maximized-horizontally', () => { - if (!window.maximized_horizontally) { - window.maximize(Meta.MaximizeFlags.HORIZONTAL); - } - this._moveIntoPlace(); - })); - this._parseTitle(); - } - - _moveIntoPlace() { - if (this._moveIntoPlaceID) { - GLib.source_remove(this._moveIntoPlaceID); - } - this._moveIntoPlaceID = GLib.timeout_add(GLib.PRIORITY_LOW, 250, () => { - if (this._fixed && (this._x !== null) && (this._y !== null)) { - this._window.move_frame(true, this._x, this._y); - } - this._moveIntoPlaceID = 0; - return GLib.SOURCE_REMOVE; - }); - } - - disconnect() { - for (let signalID of this._signalIDs) { - this._window.disconnect(signalID); - } - if (this._moveIntoPlaceID) { - GLib.source_remove(this._moveIntoPlaceID); - } - if (this._keepAtTop) { - this._window.unmake_above(); - } - this._window = null; - this._waylandClient = null; - } - - setWaylandClient(client) { - this._waylandClient = client; - } - - _parseTitle() { - this._x = null; - this._y = null; - this._keepAtBottom = false; - let keepAtTop = this._keepAtTop; - this._keepAtTop = false; - this._showInAllDesktops = false; - this._hideFromWindowList = false; - this._fixed = false; - let title = this._window.get_title(); - if (title != null) { - if ((title.length > 0) && (title[title.length - 1] == ' ')) { - if ((title.length > 1) && (title[title.length - 2] == ' ')) { - title = '@!HTD'; - } else { - title = '@!H'; - } - } - let pos = title.search('@!'); - if (pos != -1) { - let pos2 = title.search(';', pos); - let coords; - if (pos2 != -1) { - coords = title.substring(pos + 2, pos2).trim().split(','); - } else { - coords = title.substring(pos + 2).trim().split(','); - } - try { - this._x = parseInt(coords[0]); - this._y = parseInt(coords[1]); - } catch (e) { - console.log(`Exception ${e.message}.\n${e.stack}`); - } - try { - let extraChars = title.substring(pos + 2).trim().toUpperCase(); - for (let char of extraChars) { - switch (char) { - case 'B': - this._keepAtBottom = true; - this._keepAtTop = false; - break; - case 'T': - this._keepAtTop = true; - this._keepAtBottom = false; - break; - case 'D': - this._showInAllDesktops = true; - break; - case 'H': - this._hideFromWindowList = true; - break; - case 'F': - this._fixed = true; - break; - } - } - } catch (e) { - console.log(`Exception ${e.message}.\n${e.stack}`); - } - } - if (this._waylandClient) { - if (this._hideFromWindowList) { - this._waylandClient.hide_from_window_list(this._window); - } else { - this._waylandClient.show_in_window_list(this._window); - } - } - if (this._keepAtTop != keepAtTop) { - if (this._keepAtTop) { - this._window.make_above(); - } else { - this._window.unmake_above(); - } - } - if (this._keepAtBottom) { - this._window.lower(); - } - if (this._fixed && (this._x !== null) && (this._y !== null)) { - this._window.move_frame(true, this._x, this._y); - } - this._changedStatusCB(this); - } - } - - refreshState(checkWorkspace) { - if (checkWorkspace && this._showInAllDesktops) { - let currentWorkspace = global.workspace_manager.get_active_workspace(); - if (!this._window.located_on_workspace(currentWorkspace)) { - this._window.change_workspace(currentWorkspace); - } - } - if (this._keepAtBottom) { - this._window.lower(); - } - } - - get hideFromWindowList() { - return this._hideFromWindowList; - } - - get keepAtBottom() { - return this._keepAtBottom; - } -} - -export class EmulateX11WindowType { - /* - This class makes all the heavy lifting for emulating WindowType. - Just make one instance of it, call enable(), and whenever a window - that you want to give "superpowers" is mapped, add it with the - "addWindow" method. That's all. - */ - constructor() { - this._isX11 = !Meta.is_wayland_compositor(); - this._windowList = []; - this._enableRefresh = true; - this._waylandClient = null; - } - - setWaylandClient(client) { - this._waylandClient = client; - for (let window of this._windowList) { - if (window.customJS_ding) { - window.customJS_ding.setWaylandClient(this._waylandClient); - } - } - } - - enable() { - if (this._isX11) { - return; - } - this._idMap = global.window_manager.connect_after('map', (obj, windowActor) => { - let window = windowActor.get_meta_window(); - if (this._waylandClient && this._waylandClient.query_window_belongs_to(window)) { - this.addWindow(window); - } - this._refreshWindows(false); - }); - this._idDestroy = global.window_manager.connect_after('destroy', (wm, windowActor) => { - // if a window is closed, ensure that the desktop doesn't receive the focus - let window = windowActor.get_meta_window(); - if (window && (window.get_window_type() >= Meta.WindowType.DROPDOWN_MENU)) { - return; - } - this._refreshWindows(true); - }); - /* Something odd happens with "stick" when using popup submenus, so - this implements the same functionality - */ - this._switchWorkspaceId = global.window_manager.connect('switch-workspace', () => { - this._refreshWindows(true); - }); - - /* But in Overview mode it is paramount to not change the workspace to emulate - "stick", or the windows will appear - */ - this._showingId = Main.overview.connect('showing', () => { - this._enableRefresh = false; - }); - - this._hidingId = Main.overview.connect('hiding', () => { - this._enableRefresh = true; - this._refreshWindows(true); - }); - } - - disable() { - if (this._isX11) { - return; - } - if (this._activate_window_ID) { - GLib.source_remove(this._activate_window_ID); - this._activate_window_ID = null; - } - for (let window of this._windowList) { - this._clearWindow(window); - } - this._windowList = []; - - // disconnect signals - if (this._idMap) { - global.window_manager.disconnect(this._idMap); - this._idMap = null; - } - if (this._idDestroy) { - global.window_manager.disconnect(this._idDestroy); - this._idDestroy = null; - } - if (this._switchWorkspaceId) { - global.window_manager.disconnect(this._switchWorkspaceId); - this._switchWorkspaceId = null; - } - if (this._showingId) { - Main.overview.disconnect(this._showingId); - this._showingId = null; - } - if (this._hidingId) { - Main.overview.disconnect(this._hidingId); - this._hidingId = null; - } - } - - addWindow(window) { - if (this._isX11) { - return; - } - if (window.get_meta_window) { // it is a MetaWindowActor - window = window.get_meta_window(); - } - window.customJS_ding = new ManageWindow(window, this._waylandClient, () => { - this._refreshWindows(true); - }); - this._windowList.push(window); - window.customJS_ding.unmanagedID = window.connect('unmanaged', window => { - this._clearWindow(window); - this._windowList = this._windowList.filter(item => item !== window); - }); - } - - _clearWindow(window) { - window.disconnect(window.customJS_ding.unmanagedID); - window.customJS_ding.disconnect(); - window.customJS_ding = null; - } - - _refreshWindows(checkWorkspace) { - if (!this._activate_window_ID) { - this._activate_window_ID = GLib.idle_add(GLib.PRIORITY_LOW, () => { - if (this._enableRefresh) { - for (let window of this._windowList) { - window.customJS_ding.refreshState(checkWorkspace); - } - if (checkWorkspace) { - // activate the top-most window - let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, global.workspace_manager.get_active_workspace()); - let anyActive = false; - for (let window of windows) { - if ((!window.customJS_ding || !window.customJS_ding._keepAtBottom) && !window.minimized) { - Main.activateWindow(window); - anyActive = true; - break; - } - } - if (!anyActive) { - for (let window of this._windowList) { - if (window.customJS_ding && window.customJS_ding._keepAtBottom && !window.minimized) { - Main.activateWindow(window); - break; - } - } - } - } - } - this._activate_window_ID = null; - return GLib.SOURCE_REMOVE; - }); - } - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/extension.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/extension.js deleted file mode 100644 index 791c730..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/extension.js +++ /dev/null @@ -1,617 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * Based on code original (C) Carlos Soriano - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -import Clutter from 'gi://Clutter' -import GLib from 'gi://GLib' -import Gio from 'gi://Gio' -import Meta from 'gi://Meta' -import St from 'gi://St' - -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js' - -import * as EmulateX11 from './emulateX11WindowType.js'; -import * as VisibleArea from './visibleArea.js'; -import * as GnomeShellOverride from './gnomeShellOverride.js'; - -const Clipboard = St.Clipboard.get_default(); -const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; - -export default class DING extends Extension { - constructor(metadata) { - super(metadata); - this.DesktopIconsUsableArea = null; - this.data = {}; - this.data.isEnabled = false; - this.data.launchDesktopId = 0; - this.data.currentProcess = null; - this.data.dbusTimeoutId = 0; - this.data.switchWorkspaceId = 0; - - this.data.GnomeShellOverride = null; - - /* The constructor of the EmulateX11 class only initializes some - * internal properties, but nothing else. In fact, it has its own - * enable() and disable() methods. That's why it could have been - * created here, in init(). But since the rule seems to be NO CLASS - * CREATION IN INIT UNDER NO CIRCUMSTANCES... - */ - this.data.x11Manager = null; - this.data.visibleArea = null; - - /* Ensures that there aren't "rogue" processes. - * This is a safeguard measure for the case of Gnome Shell being - * relaunched (for example, under X11, with Alt+F2 and R), to kill - * any old DING instance. That's why it must be here, in init(), - * and not in enable() or disable() (disable already guarantees that - * the current instance is killed). - */ - this.doKillAllOldDesktopProcesses(); - } - - enable() { - if (!this.data.GnomeShellOverride) { - this.data.GnomeShellOverride = new GnomeShellOverride.GnomeShellOverride(); - } - if (!this.data.x11Manager) { - this.data.x11Manager = new EmulateX11.EmulateX11WindowType(); - } - if (!this.DesktopIconsUsableArea) { - this.DesktopIconsUsableArea = new VisibleArea.VisibleArea(); - this.data.visibleArea = this.DesktopIconsUsableArea; - } - // If the desktop is still starting up, we wait until it is ready - if (Main.layoutManager._startingUp) { - this.data.startupPreparedId = Main.layoutManager.connect('startup-complete', () => this.innerEnable()); - } else { - this.data.startupPreparedId = null; - this.innerEnable(); - } - } - - disable() { - this.DesktopIconsUsableArea = null; - this.data.isEnabled = false; - this.killCurrentProcess(); - this.data.GnomeShellOverride.disable(); - this.data.x11Manager.disable(); - this.data.visibleArea.disable(); - - if (this.data.doCopyId) { - this.data.doCopy.disconnect(this.data.doCopyId); - this.data.doCopyId = 0; - this.data.doCopy = undefined; - } - - if (this.data.switchWorkspaceId) { - global.window_manager.disconnect(this.data.switchWorkspaceId); - this.data.switchWorkspaceId = 0; - } - if (this.data.doCutId) { - this.data.doCut.disconnect(this.data.doCutId); - this.data.doCutId = 0; - this.data.doCut = undefined; - } - - if (this.data.disableTimerId) { - this.data.disableTimer.disconnect(this.data.disableTimerId); - this.data.disableTimerId = 0; - this.data.disableTimer = undefined; - } - - this.data.desktopGeometry = undefined; - - // disconnect signals only if connected - if (this.data.dbusConnectionGroupId) { - this.data.dbusConnection.unexport_action_group(this.data.dbusConnectionGroupId); - this.data.dbusConnectionGroupId = 0; - this.data.dbusConnection = undefined; - } - - if (this.data.dbusConnectionId) { - Gio.bus_unown_name(this.data.dbusConnectionId); - this.data.dbusConnectionId = 0; - } - this.data.actionGroup = undefined; - - if (this.data.visibleAreaId) { - this.data.visibleArea.disconnect(this.data.visibleAreaId); - this.data.visibleAreaId = 0; - } - if (this.data.startupPreparedId) { - Main.layoutManager.disconnect(this.data.startupPreparedId); - this.data.startupPreparedId = 0; - } - if (this.data.monitorsChangedId) { - Main.layoutManager.disconnect(this.data.monitorsChangedId); - this.data.monitorsChangedId = 0; - } - if (this.data.workareasChangedId) { - global.display.disconnect(this.data.workareasChangedId); - this.data.workareasChangedId = 0; - } - if (this.data.sizeChangedId) { - global.window_manager.disconnect(this.data.sizeChangedId); - this.data.sizeChangedId = 0; - } - if (this.data.dbusTimeoutId) { - GLib.source_remove(this.data.dbusTimeoutId); - this.data.dbusTimeoutId = 0; - } - } - - /** - * The true code that configures everything and launches the desktop program - */ - innerEnable() { - if (this.data.startupPreparedId !== null) { - Main.layoutManager.disconnect(this.data.startupPreparedId); - this.data.startupPreparedId = null; - } - - this.data.GnomeShellOverride.enable(); - - // under X11 we don't need to cheat, so only do all this under wayland - if (Meta.is_wayland_compositor()) { - this.data.x11Manager.enable(); - } else { - this.data.switchWorkspaceId = global.window_manager.connect('switch-workspace', () => { - let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, global.workspace_manager.get_active_workspace()); - windows = global.display.sort_windows_by_stacking(windows); - if (windows.length) { - let topWindow = windows[windows.length - 1]; - topWindow.focus(Clutter.CURRENT_TIME); - } - }); - } - - /* - * If the desktop geometry changes (because a new monitor has been added, for example), - * we kill the desktop program. It will be relaunched automatically with the new geometry, - * thus adapting to it on-the-fly. - */ - this.data.monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this.updateDesktopGeometry()); - /* - * Any change in the workareas must be detected too, for example if the used size - * changes. - */ - this.data.workareasChangedId = global.display.connect('workareas-changed', () => this.updateDesktopGeometry()); - - /* - * This callback allows to detect a change in the working area (like when changing the Scale value) - */ - this.data.visibleAreaId = this.data.visibleArea.connect('updated-usable-area', () => this.updateDesktopGeometry()); - - this.data.isEnabled = true; - if (this.data.launchDesktopId) { - GLib.source_remove(this.data.launchDesktopId); - } - - /* - * Due to a problem in the Clipboard API in Gtk3, it is not possible to do the CUT/COPY operation from - * dynamic languages like Javascript, because one of the methods needed is marked as NOT INTROSPECTABLE - * - * https://discourse.gnome.org/t/missing-gtk-clipboard-set-with-data-in-gtk-3/6920 - * - * The right solution is to migrate DING to Gtk4, where the whole API is available, but that is a very - * big task, so in the meantime, we take advantage of the fact that the St API, in Gnome Shell, can put - * binary contents in the clipboard, so we use DBus to notify that we want to do a CUT or a COPY operation, - * passing the URIs as parameters, and delegate that to the DING Gnome Shell extension. This is easily done - * with a GLib.SimpleAction. - */ - this.data.dbusConnectionId = Gio.bus_own_name(Gio.BusType.SESSION, 'com.rastersoft.dingextension', Gio.BusNameOwnerFlags.NONE, null, (connection, name) => { - this.data.dbusConnection = connection; - - this.data.doCopy = new Gio.SimpleAction({ - name: 'doCopy', - parameter_type: new GLib.VariantType('as'), - }); - this.data.doCut = new Gio.SimpleAction({ - name: 'doCut', - parameter_type: new GLib.VariantType('as'), - }); - this.data.disableTimer = new Gio.SimpleAction({ - name: 'disableTimer', - }); - this.data.desktopGeometry = Gio.SimpleAction.new_stateful('desktopGeometry', new GLib.VariantType('av'), this.getDesktopGeometry()); - this.data.desktopGeometry.set_enabled(true); - this.data.doCopyId = this.data.doCopy.connect('activate', (action, parameters) => this.manageCutCopy(action, parameters)); - this.data.doCutId = this.data.doCut.connect('activate', (action, parameters) => this.manageCutCopy(action, parameters)); - this.data.disableTimerId = this.data.disableTimer.connect('activate', () => { - if (this.data.currentProcess && this.data.currentProcess.subprocess) { - this.data.currentProcess.cancel_timer(); - } - }); - this.data.actionGroup = new Gio.SimpleActionGroup(); - this.data.actionGroup.add_action(this.data.doCopy); - this.data.actionGroup.add_action(this.data.doCut); - this.data.actionGroup.add_action(this.data.disableTimer); - this.data.actionGroup.add_action(this.data.desktopGeometry); - - this.data.dbusConnectionGroupId = this.data.dbusConnection.export_action_group( - '/com/rastersoft/dingextension/control', - this.data.actionGroup - ); - this.launchDesktop(); - }, null); - } - - /* - * Before Gnome Shell 40, St API couldn't access binary data in the clipboard, only text data. Also, the - * original Desktop Icons was a pure extension, so it was limited to what Clutter and St offered. That was - * the reason why Nautilus accepted a text format for CUT and COPY operations in the form - * - * x-special/nautilus-clipboard - * OPERATION - * FILE_URI - * [FILE_URI] - * [...] - * - * In Gnome Shell 40, St was enhanced and now it supports binary data; that's why Nautilus migrated to a - * binary format identified by the atom 'x-special/gnome-copied-files', where the CUT or COPY operation is - * shared. - * - */ - /** - * - * @param action - * @param parameters - */ - manageCutCopy(action, parameters) { - let content = ''; - if (action.name == 'doCut') { - content += 'cut\n'; - } else { - content += 'copy\n'; - } - - let first = true; - for (let file of parameters.recursiveUnpack()) { - if (!first) { - content += '\n'; - } - first = false; - content += file; - } - let obj = new TextEncoder(); - Clipboard.set_content(CLIPBOARD_TYPE, 'x-special/gnome-copied-files', new GLib.Bytes(obj.encode(content))); - } - - /** - * Kills the current desktop program - */ - killCurrentProcess() { - if (this.data.launchDesktopId) { - GLib.source_remove(this.data.launchDesktopId); - this.data.launchDesktopId = 0; - } - - // kill the desktop program. It will be reloaded automatically. - if (this.data.currentProcess && this.data.currentProcess.subprocess) { - this.data.currentProcess.cancel_timer(); - this.data.currentProcess.cancellable.cancel(); - this.data.currentProcess.subprocess.send_signal(15); - } - this.data.currentProcess = null; - this.data.x11Manager.setWaylandClient(null); - } - - /** - * - */ - updateDesktopGeometry() { - if (this.data.actionGroup && (Main.layoutManager.monitors.length != 0)) { - this.data.actionGroup.change_action_state('desktopGeometry', this.getDesktopGeometry()); - } - } - - /** - * - */ - getDesktopGeometry() { - let desktopList = []; - let ws = global.workspace_manager.get_workspace_by_index(0); - for (let monitorIndex = 0; monitorIndex < Main.layoutManager.monitors.length; monitorIndex++) { - let area = this.data.visibleArea.getMonitorGeometry(ws, monitorIndex); - let desktopListElement = new GLib.Variant('a{sd}', { - 'x': area.x, - 'y': area.y, - 'width': area.width, - 'height': area.height, - 'zoom': area.scale, - 'marginTop': area.marginTop, - 'marginBottom': area.marginBottom, - 'marginLeft': area.marginLeft, - 'marginRight': area.marginRight, - monitorIndex, - 'primaryMonitor': Main.layoutManager.primaryIndex, - }); - desktopList.push(desktopListElement); - } - return new GLib.Variant('av', desktopList); - } - - /** - * This function checks all the processes in the system and kills those - * that are a desktop manager from the current user (but not others). - * This allows to avoid having several ones in case gnome shell resets, - * or other odd cases. It requires the /proc virtual filesystem, but - * doesn't fail if it doesn't exist. - */ - - /** - * - */ - doKillAllOldDesktopProcesses() { - let procFolder = Gio.File.new_for_path('/proc'); - if (!procFolder.query_exists(null)) { - return; - } - - let fileEnum = procFolder.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null); - let info; - while ((info = fileEnum.next_file(null))) { - let filename = info.get_name(); - if (!filename) { - break; - } - let processPath = GLib.build_filenamev(['/proc', filename, 'cmdline']); - let processUser = Gio.File.new_for_path(processPath); - if (!processUser.query_exists(null)) { - continue; - } - let [binaryData, etag] = processUser.load_bytes(null); - let contents = ''; - let readData = binaryData.get_data(); - for (let i = 0; i < readData.length; i++) { - if (readData[i] < 32) { - contents += ' '; - } else { - contents += String.fromCharCode(readData[i]); - } - } - let path = `gjs ${GLib.build_filenamev([this.path, 'app', 'ding.js'])}`; - if (contents.startsWith(path)) { - let proc = new Gio.Subprocess({argv: ['/bin/kill', filename]}); - proc.init(null); - proc.wait(null); - } - } - } - - /** - * - * @param reloadTime - */ - doRelaunch(reloadTime) { - this.data.currentProcess = null; - this.data.x11Manager.setWaylandClient(null); - if (this.data.isEnabled) { - if (this.data.launchDesktopId) { - GLib.source_remove(this.data.launchDesktopId); - } - this.data.launchDesktopId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, reloadTime, () => { - this.data.launchDesktopId = 0; - this.launchDesktop(); - return false; - }); - } - } - - /** - * Launches the desktop program, passing to it the current desktop geometry for each monitor - * and the path where it is stored. It also monitors it, to relaunch it in case it dies or is - * killed. Finally, it reads STDOUT and STDERR and redirects them to the journal, to help to - * debug it. - */ - launchDesktop() { - console.log('Launching DING process'); - let argv = []; - argv.push(GLib.build_filenamev([this.path, 'app', 'ding.js'])); - // Specify that it must work as true desktop - argv.push('-E'); - // The path. Allows the program to find translations, settings and modules. - argv.push('-P'); - argv.push(GLib.build_filenamev([this.path, 'app'])); - - this.data.currentProcess = new LaunchSubprocess(0, 'DING'); - this.data.currentProcess.set_cwd(GLib.get_home_dir()); - if (this.data.currentProcess.spawnv(argv) === null) { - this.doRelaunch(1000); - return; - } - this.data.x11Manager.setWaylandClient(this.data.currentProcess); - this.data.launchTime = GLib.get_monotonic_time(); - - /* - * If the desktop process dies, wait 100ms and relaunch it, unless the exit status is different than - * zero, in which case it will wait one second. This is done this way to avoid relaunching the desktop - * too fast if it has a bug that makes it fail continuously, avoiding filling the journal too fast. - */ - this.data.currentProcess.subprocess.wait_async(null, (obj, res) => { - let delta = GLib.get_monotonic_time() - this.data.launchTime; - if (delta < 1000000) { - // If the process is dying over and over again, ensure that it isn't respawn faster than once per second - var reloadTime = 1000; - } else { - // but if the process just died after having run for at least one second, reload it ASAP - var reloadTime = 1; - } - obj.wait_finish(res); - if (!this.data.currentProcess || obj !== this.data.currentProcess.subprocess) { - return; - } - if (obj.get_if_exited()) { - obj.get_exit_status(); - } - this.doRelaunch(reloadTime); - }); - } -} -/** - * This class encapsulates the code to launch a subprocess that can detect whether a window belongs to it - * It only accepts to do it under Wayland, because under X11 there is no need to do these tricks - * - * It is compatible with https://gitlab.gnome.org/GNOME/mutter/merge_requests/754 to simplify the code - * - * @param {int} flags Flags for the SubprocessLauncher class - * @param {string} process_id An string id for the debug output - */ -class LaunchSubprocess { - constructor(flags, process_id) { - this._process_id = process_id; - this.cancellable = new Gio.Cancellable(); - this._launcher = new Gio.SubprocessLauncher({flags: flags | Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE}); - if (Meta.is_wayland_compositor()) { - try { - this._waylandClient = Meta.WaylandClient.new(this._launcher); - } catch (e) { - this._waylandClient = Meta.WaylandClient.new(global.context, - this._launcher); - } - } - this.subprocess = null; - this.process_running = false; - this._launch_timer = 0; - this._waiting_for_windows = 0; - } - - spawnv(argv) { - try { - if (Meta.is_wayland_compositor()) { - this.subprocess = this._waylandClient.spawnv(global.display, argv); - } else { - this.subprocess = this._launcher.spawnv(argv); - } - } catch (e) { - this.subprocess = null; - console.log(`Error while trying to launch DING process: ${e.message}\n${e.stack}`); - } - // This is for GLib 2.68 or greater - if (this._launcher.close) { - this._launcher.close(); - } - this._launcher = null; - if (this.subprocess) { - /* - * It reads STDOUT and STDERR and sends it to the journal using console.log(). This allows to - * have any error from the desktop app in the same journal than other extensions. Every line from - * the desktop program is prepended with the "process_id" parameter sent in the constructor. - */ - this._dataInputStream = Gio.DataInputStream.new(this.subprocess.get_stdout_pipe()); - this.read_output(); - this.subprocess.wait_async(this.cancellable, () => { - this.process_running = false; - this._dataInputStream = null; - this.cancellable = null; - if (this._launch_timer != 0) { - GLib.source_remove(this._launch_timer); - this._launch_timer = 0; - this._waiting_for_windows = 0; - } - }); - this.process_running = true; - if (Meta.is_wayland_compositor() && (Main.layoutManager.monitors.length != 0)) { - // This ensures that, if the DING window isn't detected in three seconds - // after launch, the desktop will be killed and, thus, relaunched again. - this._waiting_for_windows = Main.layoutManager.monitors.length; - this._launch_timer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 3000, () => { - this._launch_timer = 0; - this.subprocess.force_exit(); - return false; - }); - } - } - return this.subprocess; - } - - cancel_timer() { - if (this._launch_timer != 0) { - GLib.source_remove(this._launch_timer); - this._launch_timer = 0; - this._waiting_for_windows = 0; - } - } - - set_cwd(cwd) { - this._launcher.set_cwd(cwd); - } - - read_output() { - if (!this._dataInputStream) { - return; - } - this._dataInputStream.read_line_async(GLib.PRIORITY_DEFAULT, this.cancellable, (object, res) => { - try { - const [output, length] = object.read_line_finish_utf8(res); - if (length) { - print(`${this._process_id}: ${output}`); - } - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - return; - } - logError(e, `${this._process_id}_Error`); - } - - this.read_output(); - }); - } - - /** - * Queries whether the passed window belongs to the launched subprocess or not. - * - * @param {MetaWindow} window The window to check. - */ - query_window_belongs_to(window) { - if (!Meta.is_wayland_compositor()) { - return false; - } - if (!this.process_running) { - return false; - } - try { - let ownsWindow = this._waylandClient.owns_window(window); - if (ownsWindow && (this._launch_timer != 0) && (this._waiting_for_windows != 0)) { - console.log(`Received notification for window. ${this._waiting_for_windows - 1} notifications remaining.`); - this._waiting_for_windows--; - if (this._waiting_for_windows == 0) { - GLib.source_remove(this._launch_timer); - this._launch_timer = 0; - } - } - return ownsWindow; - } catch (error) { - console.log(`Exception error: ${error.message}\n${error.stack}`); - return false; - } - } - - show_in_window_list(window) { - if (Meta.is_wayland_compositor() && this.process_running) { - this._waylandClient.show_in_window_list(window); - } - } - - hide_from_window_list(window) { - if (Meta.is_wayland_compositor() && this.process_running) { - this._waylandClient.hide_from_window_list(window); - } - } -}; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/gnomeShellOverride.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/gnomeShellOverride.js deleted file mode 100644 index f520d04..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/gnomeShellOverride.js +++ /dev/null @@ -1,147 +0,0 @@ -/* Gnome Shell Override - * - * Copyright (C) 2021 Sundeep Mediratta (smedius@gmail.com) - * Copyright (C) 2020 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -/* exported GnomeShellOverride */ -'use strict'; -import Shell from 'gi://Shell' -import Meta from 'gi://Meta' - -import * as WorkspaceAnimation from 'resource:///org/gnome/shell/ui/workspaceAnimation.js' - -var replaceData = {}; - -/* - * This class overrides methods in the Gnome Shell. The new methods - * need to be defined below the class as seperate functions. - * The old methods that are overriden can be accesed by relpacedata.old_'name-of-replaced-method' - * in the new functions - */ - - -export class GnomeShellOverride { - constructor() { - this._isX11 = !Meta.is_wayland_compositor(); - } - - enable() { - if (this._isX11) { // ** X11 Methods only - if (WorkspaceAnimation && - WorkspaceAnimation.WorkspaceGroup !== undefined) { - this.replaceMethod(WorkspaceAnimation.WorkspaceGroup, '_shouldShowWindow', newShouldShowWindow); - } - } else { // ** Wayland replace methods below this - this.replaceMethod(Shell.Global, 'get_window_actors', newGetWindowActors); - } - } - - // restore external methods only if have been intercepted - - disable() { - for (let value of Object.values(replaceData)) { - if (value[0]) { - value[1].prototype[value[2]] = value[0]; - } - } - replaceData = {}; - } - - /** - * Replaces a method in a class with our own method, and stores the original - * one in 'replaceData' using 'old_XXXX' (being XXXX the name of the original method), - * or 'old_classId_XXXX' if 'classId' is defined. This is done this way for the - * case that two methods with the same name must be replaced in two different - * classes - * - * @param {class} className The class where to replace the method - * @param {string} methodName The method to replace - * @param {Function} functionToCall The function to call as the replaced method - * @param {string} [classId] an extra ID to identify the stored method when two - * methods with the same name are replaced in - * two different classes - */ - - replaceMethod(className, methodName, functionToCall, classId) { - if (classId) { - replaceData[`old_${classId}_${methodName}`] = [className.prototype[methodName], className, methodName, classId]; - } else { - replaceData[`old_${methodName}`] = [className.prototype[methodName], className, methodName]; - } - className.prototype[methodName] = functionToCall; - } -}; - - -/** - * New Functions used to replace the gnome shell functions are defined below. - */ - -/** - * Receives a list of metaWindow or metaWindowActor objects, and remove from it - * our desktop window - * - * @param {GList} windowList A list of metaWindow or metaWindowActor objects - * @returns {GList} The same list, but with the desktop window removed - */ - -/** - * - * @param windowList - */ -function removeDesktopWindowFromList(windowList) { - let returnVal = []; - for (let element of windowList) { - let window = element; - if (window.get_meta_window) { // it is a MetaWindowActor - window = window.get_meta_window(); - } - if (!window.customJS_ding || !window.customJS_ding.hideFromWindowList) { - returnVal.push(element); - } - } - return returnVal; -} - -/** - * Method replacement for Shell.Global.get_window_actors - * It removes the desktop window from the list of windows in the Activities mode - */ - -/** - * - */ -function newGetWindowActors() { - /* eslint-disable no-invalid-this */ - let windowList = replaceData.old_get_window_actors[0].apply(this, []); - return removeDesktopWindowFromList(windowList); -} - -/** - * Method replacement under X11 for should show window - * It removes the desktop window from the window animation - */ - -/** - * - * @param window - */ -function newShouldShowWindow(window) { - if (window.get_window_type() === Meta.WindowType.DESKTOP) { - return false; - } - /* eslint-disable no-invalid-this */ - return replaceData.old__shouldShowWindow[0].apply(this, [window]); -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/be/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/be/LC_MESSAGES/ding.mo deleted file mode 100644 index 2f3face2f35c24ff6039d0de17caed42c1f1aff7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19373 zcmb`N3y@q@na3}Rk3>MlH{g1SK#0yvX2L@l2$EzHg63sr5LQ{Vr~786O~2?z!tjtJ z0|ZQ9csU}N@DdhvtqqV6$#V<0)T%ADyI8B%DrJ4FTUyrcTCTh6?z+0a|98&4-96Jo z26wyW%)jrw=X~co-}{`~FP(h+X9GT8qMb&|ye0^K3jW1h{_(lsq#)=AF9er@Rj>=( z51tSH1K0ze`oIcHTVXuU;E}Dco%pwsQJ1;%|8sj4a|aX1#boy zfcJyye*{DX!QX-W1uuF06?hicuVT_Ozy;vh;2Kcb+L9J&9l)Td5tHGN=h6LlF0=)D9=UcUjw?{O?f>wX=m=WhYu z2`&I7uce^+e+-m-N5G508rTay18Sb1f@gxi0r?9~ftYY1I0qa6MSl(dG+zcB220@k z!52ZT^ADi9>72Gn{U12K)@DNyqM8mMtU1jYY9 zgQEL8Q2kG1u+}#Zl<6)67lHkt=E;L}4Yq=>0v`ay=R@E;@DWh!`8p_ld>7PwzXXTC z-+|))BM9~NU=6$k{4}Wf4}+Tb>!9d<2b3IN1f}o)1SJm{ndr_1Uk9EF>iK&?jej3_ z3V0rP8Mw~he*l!e9tXw8k3jKpJe}VSo(Reg-wz`CU@<7a90b*Wn}7bKfBrR4a{Lb1 z1^xh(9Okfi>AMSD2rdEVgV%zx_s@gs_W~%oKLe$wIRuaMz;}Vt!&(rM!PTJTvl-O* zo4|hXNsuK3KL+K0{|$=oGg*wrUj!oZV5PtQq{lp{`K|}G{?CBR!TUh*`+ZRQn)4?? z@Gy7{I1c_ElwP)BG*^M!LDBgUD1H126u-xXuHR{(^m95Wxh?>^!HYmt8Du?f17SUQ z2>dwsHSl`yt)~aUjo<`$@Hp0l&}v+N3!!ZXFTto~Ki>ew&ucK2G2qn5?Qg&+;;`F0S|1W)LeD@Qf<~s_C&+mix zf&T((-f@ic0zC(h2Y(Bm1pW^wIh}C6vxg6XnkNm)o<0XY1s(z~1EUYP`MwI?!1V#} zP2l+ue>->?crthmxD>n=l>P1n-wl2j#6*LC0yXaKC`ULSl-w==HUB!W0Nw(=4g6QI z1kULv2ZPsxTKBg=OgZ=-h$@3WfSPw9i~bZ?2G@c=1SRiolqdVT8WbPfz%2L`Q10g z;4biE;LpJa!DTG!_uxz5cflXhiRsPu0E;yb=nJ37f#pwqeV4yJ6_hM7EsMGScJKwh zyoI)fCK=yMLv6vOv~{#$+AXw?(mqd&Yy(jTchdBEjRT8?`uaFccB9Xuw3BEHb-`zs z1B;`l^ZkAP`cE8&uKI;vFWL2!MP%7kkR zxv_a+u^i4@Q!GS|#Jn?ZC^?dAQu*knd11B^7NRH ztHm%=3^$KPg)o<@71E<(F%^0`;f8WCAHqPGaf5>;nM{}}gi)R~@}wB1Y6gO1ET(+>W(lfog-JgEDImVt9qRnBZoZS>vG==6bmP*A+wi<;M<_U`%>}Dlh zj-o=~B)lqSpX<%3F;-|0Zj2(o=5R^5oGOeUj^QyIpG#G$VJf~^EN7x}hf#yoRC;5S z=?Vw4`D`v#4y$7&7)zC-aHL$Um7+|rq+qni#8{?vy9L;MPUJ*abX;WOUHV8ke8Vr`ys>LN`(|ECp-BhY5 z2F{iitJPw@I~Spobg^7uh5lAKJ2Kk5S1xYE1Y#4BjRs5Iy;W#3Scc9E5RUSxY!3Sv z$d;pYwOAfYo)k-rua07JX5hn7I#pw_S(uTndt!rQd0Bu)rK6k&_=LB7sf>YRlfkl4 zX(?Qa*d^dX<|kX843_00M8B+7E@NilV3cEi8Srp~ZAal6EM|}%=}~%S(;H37X7
  • +;t=!CxS?39mTFar`lk5_ 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ca/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ca/LC_MESSAGES/ding.mo deleted file mode 100644 index 8eacc569ba2c18f06310e61be4d51d5a1ed408e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16248 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/cs/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/cs/LC_MESSAGES/ding.mo deleted file mode 100644 index 2ad6518a955b5fb1c16a42114260e5efbe5cd572..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14996 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 Bm23b2 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/de/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/de/LC_MESSAGES/ding.mo deleted file mode 100644 index d593279971ccfeca43deb5399573454cace509ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8806 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 Vmr&*4#gfBv93(2jl#X%Q{{ncU%+3G+ diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/es/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/es/LC_MESSAGES/ding.mo deleted file mode 100644 index 9d9478a908264a7a0afc2cedb08d9704d0e7edbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15136 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 OahoJfX6e{8YW@$7MQ*|X diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fi/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fi/LC_MESSAGES/ding.mo deleted file mode 100644 index 203b0796c7212ffe69bf94921359f35d723fc7ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12290 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fr/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fr/LC_MESSAGES/ding.mo deleted file mode 100644 index 6c9673c24b7e94af833400570ae7a623878f1d24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16089 zcmbW73yfS>dB<-cgk+Nd2>}8La4>-+u)BUhLa<{uYp?A%@eA+f!JE4?cXw|*bMNHd znYGu!!~_aSS_%{hq%_6l5wZmeDzr^Og~}@-RaGe!szfD7Arz@9;!#RP%d@}#ch0>t zv-aYM(VqR!J@-7n_xa8|a^acpi});2E~PY|5JlesKRLobKG!@ciZ+5T2e*P;MV<*> z4{9BIK<#H56ulbYjQ0IRQ171# zUJPCdie6hmwSN^T`p$vZf<15@_!pq&`40F3@FyUD(X$v#xE4GIoCG!gUjAvmCO89j zz!!sG1GUdzgKB>!o6x$S1U?@e2Q|+DkflcrQ2RXuYMu9j+RukUL?e0#6uln?)$g02 z*8c-g@3)DK!r17)C^Fhhsi$O>qZ3d;6Q=r=472ZD>-aibA zj$Z*s!Eb<~!#QkT{2m3@f)n87;O(H~{eDpGPJkNsyP)`V4#wju@R^|aun%O&=ry3| za|l%bqu@sHL69v(-v*_BKL@q$7qA)i-vmPP==$*dhJbBQ^Bn=T|9iph;Cn!=_g_Kr z>zwCA(TBj-fo}nS1&S|sAvCvwZwEEbw?OgZN1)bwhV$(%1;wA|fuie`;25|Ggq2Ym z@Gg+0M;`=V4L%GW0WW%96ul9ACwTM>_5{&h%k#Yu?HKqU;EiB=LGkm~py+xL%#=Pn57fG^ z0;LxRK+!)1Az^eUD1CSUlpHOA3HWvJiQtwi{J1+nNE^Kx+zcK8Sz7ckcoz5wsQJGO zO5T13z7#y0&1u}t;5x7cLaOKi@Fn1vz}JBP4Q>bbzsRreK2YO+GT>)H?f3H_B#r(t z)c+SK`TE~be<8+6&sT$5?|xA9%)xWPyTP-;_ktSl0T7XhJ_CwQUk&(uP;?v_^>XtJ zP<+1voCMzrI`Hp7*`NOeMek?BEYV>-D7(J{6rFAg&v$@t;`v^10z3!eNbYU~wVv04 zurTU?{6+8QpZNA=(1G6!_$!bpqvxUwqSJ0r^G<=VE}91==kEg5{}UinMkheE{}CvC z_$l~g@NAf~1H2fNT)ZBHCDBn(a`16b{XQM){|bB(&))*Y&mV$X{{`!r8@vpZop=X$ z9=HrjFTM(DoNVzZKMeZUDufL*TjKF;M*ZeNgQ_37!vr4!jUN0cyYh0^SJz z64ZWnAzXXFSAyEd$3czv&!FVzo1o}&20|)1xft9Jz6^XBcsD3I{2i!vkATvf{{fjI zI+x8Ma?uu0?NV?H_;wJ{iM|~0$DrnW&ec9n+6q36=Pr0NcrU1ReH)bgeIFEkMp(o? z@B&bFECwNQ^m%X>_&w0{`WoN=04O1>Xi9fQV;+EYCi-@c#qhyX=xaBOXl8_4N|U0!8D#ol<@N zm@iMI9HU%Gxs$^5(RCE@dWP~=%FUGfDF-R~JVbe=ee*ghK1g@o80vlplnm;Fxi>w1 z7bregACo~IZU_~KThyYIl#fv)v*ODXMRxBU6n&oH!E{kyKSG%fb$<$qw`;@m0|CWH z>7e9MpT|+et2a=@D}6+3eI!HT(`zZ0Qf{X_gCgEEDT|cXQ7)!Dh4Mj4_1VprL)8O# zE9KRcyD8UG3d$Vi_bAl|aWQ#lfDclhO?e+hGN_Muex7~9CWF!)$&)^k3&bMoP;R5V zlOkEXks=%XCW=1C?Z3A>`g#=wF^cY>yqluWU6lLmTmRp4`1*$w$>*7rt10?)DeEb+ zpZfeRrDxx;L*NzRdj)?~eF0<2S>gF!@G#{y;rVRv!{PgZfH#4Ur<_Y!qP&WN>P4ub z#R*5i!Ou<}9Ob!`S5R`wWfXlrO8F4w{d(Z@0?Jm(dnlN#XfNdtC`T#!$Ua_V-_TRA zP5C(G&6KxL?x92@*UoI&p2ah*#O0lCnrEYK%|xq}A9C9dCyib=&F0*Wl(%u|VzC?tD^|Zlcjh%5n_@9!TP*+n2Q#*SNfJ zYxd?@;)hss*&Q7}t_EXA6Ai7;b#vFu-J$s; zbFH|SHRiR%*oAT2Y>~Ge3vf-}IhtrTU7We3%^rD^yV$nJm$aE=-E?-*mHBMfwbJZh zIev0;t3SEA-^bo%$syM)(uJhd6q-Npbn-IoCaz>2m(N;d*(j1Ei#&yQSIg)5P`t*A_1FPcelie6LQxN$IPj=HI|ownk_br(AL&B-@~*QnG-sKF?zEgm5?E#d(H9bz!80Cgg>LKO z_&C%HPl03MX`f$bc@Vb6UC+U2qSwtQ3gdX*MQ+M2jA3P4^KLh9kF^qb(#VU99fqnR zoty9175PC#pb`BjAT6wHnrH61gKXdX$4@NtgYQC5O8EN+BPpPxvh|01kRd|9(yp_)=D7#wq8*n zW^O8JF~0nbq)C!%*mB zCn>rqOrcFD?xs@YLuq$jQjQ2F1$F30xmb3SHsY;jTD7}l-BDxb$u)kgextl4DI4x+ zb^V5#A}qL~N>u}AQHaYgyCd&)JH4(*ef08rw7TOdo4I+c&I}6U8b*DQJtzX4D*C&5 z%)_v{R?0iF+YJd%wEZ@uE85=f zbQj%p5tsAPcE%}W7~`@$gr#s8KxauhrTgcjrBaPs_T;*tz1&&}?4R21c-o6(XdyAZb-AvAGhWp~`B8NDKEi zZAXf->9KTl3tWtL7_UPMh-ju`77rvzh+8R?N75nnK~_@r^1f@-E#^Jf?qR%xp>rp@ zzD$jZpsM51^;o->Sv>P*Xu3mc8aOu3yvZV-yF9ymk{8kSIhI&97iV+Cf5ZP)Zo*Us zn}&;&wOEXHWecpgIq10uHflSMZj=+Mh7h-{!t8ooJy;ifj;{(2rmQ#>b>AHqa|!?D zvCWl{b_uGtY0NbS_5{(kDFz8wNKt*{HZi}uHu zSR-jGo=IA+n;e#yxf!HIqKM@u{KB3bnrCC$v2BnNCQG}e;jbr1A1AFHw!#j4R%qewg5GV%^M zfCycE4HiNgTiNySN)|rN8m%5Ce=vj?tu3dKy;+48lF8Tvm48Lq9cLUi*)?maP}v)J z#WX%nC5j~yP_37pLn$KS1&E;_oM}AXs_HEDwiv-|LU1qE*V=ghQaKt|&J*%Ay3q$+)ES@5wmf=rt($8wXyd{2ozG@GsVy*n_Xl`l}oi6m;oZFYt<+Ot`dSgsGt;I-YrPX3u)5K%vJL!#t{5G0=(y`N>Y-ZeTz>Z#i%BuBf9pYvg>7&=P03CvT>+ zDZ(_J;x?^6wK{ zDx8mX8j&`cKwHpWDd8^jE_-*5+bBMA_I71OAdLqiN^LH>zgaqN{HoTc9u ziDAWZ&LNGV)B3nOVDUvbe&i1SON07MF)EqQHjbK6H74=jgO3+qdbJBm#)|h5T@*#Ok2BeZ^;T)DeFFNnTX*{ zTW@Hr2%uXKbLk|^$O9Am!~qk#X?E??AHEJ|k2*VOj#*$`(O@7?67nNHl%c&(WlX2p zV#H`{%N97qSJ@36sE|3W&hjLfd5o|g$BNwRPu5%uG3U}^Z2kC#vAGO!_orkA?hKuX z^*nSOmh8#L@6hlPD(&86Gr9?P%RjTAAoCIy^aYl1!0pA?Vi@X3p_W?)B4(`4ImlPt zdc_-i;Uf-ZZu*gky+9#2--ftE?#eePqg#~5iJQ`~%IGRAsH{7aNFIVXkE*3AERCZV zzahsm9>%sHSi^grV(NM{MlWSnG-Jb`;5DeFZRGmH5lmKR)W@3Ev~opzgDYaYgb?2E zc~j%3ZlV;*ObrC;)rnkbwl*|@Q<~7i`e2vm3Ig-txBv%^q$nCdoy<=sjjn$sVEL31>I9-e!NIGnPY)?6tHpjO1=E||@e4`uL zzi;e7vXH9d*d*cjMz>+zh7Duu*Nv@viCcfo#;acT;&mI=tsB|RC}UXItZd1YZFH0I z!XidF~Ue9C58jkKJG8RZo24#Br%}k&?TxH_74U zCFNKpls!xVi3Z+aEZT`9j13WNJ2`Ru#237!lNlOw&E=)pG{dNB2Gpa-F>mCY?vERd z<%dewWP`lm#Me*FBGw!(wFZt$*dmSTmXBMFGE+SQ(K6|^Y%<4b)i-VQGPQj4*rzv{ zsol*iit;jvhdg9ILF*3+958KfasPB^^>ff}&*ZK2_FjTr z^J5eudp$@@0CQ5)-=d|a%<|p>Ydu_>HgdvcH*XwN=v%@Ww$oVtTz7fN8#Ry?5+6ha zfwgq$sU!#2&}09Fl5rV=#aUNlk+RFQU5;lkmZ8Y;0tC#=k|kx`O#y!0t$wY31i#Bm z@>S+hP%hqD##|J`a+=k#eDd;AiDPkHIlj23+0eY@KW7^I9xIo${18ItPZOEg(jS!O zLG()rWCr(0`xS{#RdaGDp&w{b<>L0)>ewFEPlvwxS)*1vq_W<6G)W#fgDCFyUY@$y zm?K-2fzBk-WM(vLIH)c!K}`&Dn$0dR6=?#0=HgysUa8pOYSX=FM^N2cCwJC5QHNa7 zZp6*az&wWC)yBP)mZp`$CfP#1$f^*#rt1BcAQM^Rlyvio<_J-dVj*gZ5!8@E=gi1h z@m#P13?{K15O4+;$vMs0%(i0%jPgA_68c$&;`ejBQteoE@IU0X5h_i=s>H}gkG&fc z%PKlTEsBwq zR75+Z&9*#aB5diBWnYlE;q5SnFbN-$3}wONg``0sL|#Z^DFH6afJBPyhdV87rq8{= z(-55%AuDcnc$MmY(wi-lEIM&KEOSNsy1w7R?EJvKh&+wczoCU$a#`Y`{JB}r-8!4s zR}iM#6~Vj%IAu5Dk>w>>nTo$sA>*x*XlaSR?{U2SEeDqx5m}IzLUM+4>~%GC>LBOj z(`i$I$w#H#dgIgUID$$o5E9H+b!24_uCa;%=?gwlZr2iWLvmr%33fr=B{+`#Sf=*! zLvn}Sea?!4SmbEJzDcNc=vPLbmDDbp1S;E6+Q%r@cjIL0>zsVFe2>B~7I`yf)6|1A z*i1q!mqa%wJ>d~o#spfX|7`+xHi;GD#)oXYj1H+@vz0@vUis4GnRsa+U$2#=jnwD4 z^?+BvL_8P;_Z=E*KCjmPLeERgP$J*LgvTf|LkoGVW3LbyBI*9(`X->SDyua(NmDHU zZ<;dDrIPx=8-TuKny2Y=`9Ni+U<49UYgcgBL5M=9Ag9qb!VabA{I!7H3-o>YYLOG_ zqPue47KHMpgJMMVjBF!94e3Z z$DX4ZD=d4wSHG+d;fCPMjb8xUe(MQr^tf?Yx!O~>T}kpdE8!MV2qm5t{B)1bz- z3t92Lu#7|mw-rQ13e1}#NEHy^d$_wG>g#2CZ-yywh)72R)D~fLYdB78!!c_jg-|}Wg&}H&Ii(?dna?$By8e5s71UsI%f#ZXC;ycKlcLyFF28@U3H)K3ys;c`Il4Qn&?*{XB9kfU!!2-ho5me)fT~cU5E82j$_o6ZKxtEiwHu7!QTp5fOMGS zd#k?;#oSdE4-Ke~y7GYBe-V%)nf0=U`_-ne5jW;_wyc+F$2;8?;bTj#fjI|Yjfb}! z8V^rkT&mWCER;H@w&~AT4*&gVufOW5)v61vgeF`8$x~KyueN(Ar3)nqgTzC=9%0mv zNi6CfSjWkO4{vB-s?#+c+~0u5S#3Plo4MrM~}Vtv}3guq{N6lBbi6xCdxvNw%v>QUnJBovFn5172-6=H9?GKDSsl!|t50#Ba`3T)Edv3tg%#vB zZtqDVDocVFRmN9Y+fj1*DY;lK*;ZMCjH|gbg&f?tVJNtA>-j4;f3Va3YWM1t+=&-8 zpAuRqa6bub{?GfQaAsXz3U_byR&-C8>IXDv8@!kBN$ggVTeqF~U1(1}bsi2yRIJ>Ho4`$((NcyfQ}Qn? zO5#HdV7Xq7+`;plk_}3*PlV*Xj>D@Z?BxY5A-;!u?y^Dp49n-IC(*v3NRnJt+EHH3 zoKN4Wg`^FhXOwe!$O8mRLF2(2LHK;C+dvDrOC4QK&P@(f``n~bY}ksL{HIQ`Rw+Ot z6uHHOb09IN{aD!Yji$giS&ArJ7s`JjTy}TG=v5@*t`OOFgaAZjy7HvNUS+trPV^%d z{sz*nD8hMQ(7^SZnNUJoYsrJ|6jwy@{l=(;e_!V98O33`0nxbqs9#D|9bZ(v-Fm$nucdWYxSXWDtT|xL9d0d4NLBf7hKA%%Um`)3-;zyrUUtZ$c3*jNC`;QLtZwilvpTBU@=V{M;>lS8 zu44UWWqStvJXV5S0+D%rF&V;~6`r59anY%)LcaVrKIdT>1q^6`(Y0IzyC0AKAC^C+ AHvj+t diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fur/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/fur/LC_MESSAGES/ding.mo deleted file mode 100644 index 42c411df5368b96d209fc3100155beda92bdeaf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2715 zcmb7^O>7)B6vqveLKi|HKxv_X`RXUL-2@@EOG}$>HfcmcR^3eiAtam`XV>YBJ+eJ% zQv^aP5|;`Iq+XHep%qduAP`7B?gb9e0~aKuiq8{Bh>ru}0Q}!%HVK7LVU6cEwx6Hh zdwy>&4XiuO&;s-==&xMG*naSbtMNkn@*2ka!LPve;7{Of;BVkMun#Yq9{@4MHiHA; z-Qdk&1-up<25$hzz#G9P*atoj;$a%E4WI)_{zZ`1Pl6=>I#>eV1j)3wK|Jg{UUz}- zfOOs`Anm^dlKi(I9`++%r2kj&I`9vW>|PIHlIsH>05^fxgZseS!8%BGJPVTF3fu<1 z1a1eko1m$WKRPmJEp-JV*VUR_P>Qml7AN@Js%e1 zk3ib@X~EAxiu32-t>E_{`S)irzX69)+_r$EX9q}n_ZH&=AdX~HAnl(4Zvy8*@^`UV zf3@Ii;JuhX4U+u(AnE%Uq$DUEl`=zX2b{xF5aa$oNOH>1<}+tD|o_Zr2z*Ld#(q`TXSPBElLwbE-3 z;bR9n#f^NScu*|hYMxs_?i-O}N_j#)Qd}rjz4jnJs5U51sZsv2;W#$O_=L!G*ipL8 zYC?xHX0?vcZOIRb@MznbOh;e8e3sQry2xr)3NKkL^K3-M(o3F7n+Pqnj~Cg9a%n6U zc~g21b&l2NW$0NwN&O;kS>ZaYe%xCTdVW}1xjbl@a=FY7n?$nl&}i<|3CSjeZA&(3 z79{tk*!`qD#z#z;B{+}KVARBsv~21LHkC@9zxY$iclea=NXv)QG*+ST$`or#^A-$N zTEwg&99(Hw0~frKjvbMa!ApxolEcl=s?&>w`(xR#9*$YrCLjs=U;g3XaGHMH_<=BxRKkRR;G4l}Ccg zqkL$nI#k(J8LU)F6VMVM`Lv6LH@3=0#jHX?nM8QLZ?5diX*P>2IoM8wip!x%9>*Tt z&O}=VEh!T0uqum{&=Ak;!B~}zZLbJbIc7_f-xZjQH zQ2H?*c7%1(@1Jgs276ZI$i_KogSrk)g!-xSJ+sP}o({&OmUhYbhLMr-e5gEB9xSm2 zav8a(^nyatBB;YUi&35;nN>*7IapAXuEMO9lC=cB>ajuzAhCo+4kxKqY&=Pg^Wp@e z={Ta=eb1smEH1Wt!BSx_WHN%v&@70MYPY3|MIMS(1DE9o&I>283pUaHdtq*+w8u1+eJHF)?XelbXHncUO4{zZ0z5@1bKlD>NeMcpzMo9DV`dco30=cSz&eO~jV4L>Br7W(raf=A}W-Sdvef=A2F zrPAdND#s&KuY(5UnJWJ+rudOLGL(KQv`U3Xwcne+Y*@Hnls>so?8nLfSc5LV>frw& sT3#hfHAg>{l{;Qr?-gbLTk)#QSR;6>p}OZNm6!h=OPP&COsK5bU(0x=QUCw| diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/he/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/he/LC_MESSAGES/ding.mo deleted file mode 100644 index 7b6495ae09d4d0b196ba008a1ad22e44da8fad5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3649 zcmbu9Pi!1l9mgM#QsS0>ZCaod`k-yvlI~{hq;cioLSiSWA&!mhlw3GWc3-^H?9Qxa zW@8*e;ea?hwwJ_>>n2WWJLZ6LqK8U|6Foo=2pEY22oM(zNC=e^2R`4o>y6bWLW0?S z^O^UX-}}Aazc+t)U`NYv9bi1l_~i$T8G#o*#Et9f4r4wJufY$)TkvD>&CdK6a2NA; z;3wf<;1lp&$lpA2k1;a!7<>Re4nF}8z=z;5ct89Wb8hncZFn#IHI&}(;YZ+Kq4M;1sQ9I%{5=d6#~vs@55h;_ zi%|QOq1J~``z0ODK>p?ew+6NQ0hHZ$QI`IFI3qi|p#0biABF=^_5KEQFzUSjO^1Jk zpF#dN_$j!9#j^7#l>L4vd!wECDJcIV_#k`*5~7*!ykCOy=O>-{oA3$d?{wz>gwHbH zNz#?~1KecqFqFLscpaXBsG1&D_{=-&;`jeg$R!Pf&gN z52(K0LGx(-AVg$#L-oTx_%wV8%J1(%<>Lm_K0kwd;cubhz6WE9_kQU8gwnH}`2k3| ze5|son(9(7%CD_Uz4t8RsVxDNJzYApI$NJ(>}SYNUFxT;OFqgU`KIe}hVrBwC?8*7 z=u)kfx91r97>e=JjO~~Da5qD76d6x4N{p>beXTR6ycHOV-!jx^w2?n=UxK8_=lB`; zdB*mumx=mKJxz*?IaI5~Gxm7UjLOw8nr1!|%%JhN?j{ z?d;*8e0DmCn^EP@-(NFBalIZy6&uBwJtLtcjl`v?{Z8q-_DooF@0X;A8nb4onVDf% zbD6UZmte+4S#8z~hiRi0%-TtpWjK|Z;W&CKv+wnFIBuS`W{RiC9W zbM?EvNX^*S%~-=l{-!k8Z))Kf{wDTNqd@|KER3UKvDj7VKHpijtrtdiioAzWP&4B} znmIF`#8e^+U1}yAm7j1vgKenXljS6AWT}~S)I5u|O}9*wReGr!Rw^!PC(n3ESSLRu zw^=_O1!0Y~(qo%6W@DO0)oBYeRnCT#$4pZBZgnTA6^e;3QN^Wav$)~aFjfz0H8Yvf zgF#X;Q(-h~PDZ$XGOE*#nL<);6hFq%$>mBQiXbXu5-5s!}* zCfvDDN`>Jda|5=o)Yn@m^%Z*iZEyd;bNzcteWg;*agtS_8KSfnWN|WJ$Lf?~q&Qi$ zU#7v5FgqWX({gntNV4-^ovsshu^iW5U|}@fBprn*7u4BsYd&DBu4i;)^vG==dyA!> zp*YHDpTg8^179-t?QAb6Ba9B(ay3X&mkpkrI$C)Cww_!%TN)fJ zA?-uD@0o)=rwYeh;O9$;d{&p0BF?yuo$E3+3X5(qea+L3x#) zi^@qmxQ=TpxVzZiubY0`{gATub|nodxo(MQRTWzC{=I6+$U=ToZPX41^IoEu-Y>IS zEE^lBUv787-L!m9bTk#q-R=E9nsb;|mv5+ea^;ddU-pw$eo1-0qTDN!b40yH1ioXG zUo9k@ITmf`lY57CUfi|(U#)EOLb}RwE5EMlEim=Xz2aL_+h1jn7PXGLcU7rx(fY)) z?U>SS@16T2yNPXIhPIV<7ZbhWS@v#kJ0bF5jXv~8xN}U^Yb}gydNXX&Rna%4T{d(G m{AbFL&CB`g2A}4!u&m6lF64>gr*4 zPaHIgi7}dR@Fp>O=3-)^Attg{^~ym-J$NxjV>BK(`2Tu(b|-{KWvYKuRbPLPe^vF5 z8&{uYXde2b=x?rKY#;dhEqI_^zLl|iz@Nc2;9uZ<;D6u-aNTOg@MD|tp!KaFme>fm z5!?x`2M>a`fer93@O5x4D8Y501@U92@wgLw3ncsZL0UfxlKm%O0Xz>4z&pT6@P4ocQhW(g-3ho2d|3P^f!IDZ%{ftX^4LGt?wNO>FwZwF6+^Uyp1Nw3S8B)h*sihl*%1a8D6 z+3x^h%F6k84|q4m2SBR3p05j#@@VJt^ZED;Ncw-2k3R*;-{&C3{|cmfzXM69AM*9z za{d95&i{a9zX3-0%eLn9K=L;R(thm&Desp-@;d`=2j2kcy))ob;D;d9`vpike+!b` zui!J_T5J-H$G{!n36SjH1vi5qgQV-%AbxBK5Ay$gKE4D(<}CMn!N<@kAIg>Xht9r- zPVHHAs%;1QHgwuoYNQ+0^f)^0EybmrXn&|t-n0jU#s_~u%I#_Nt@#|?kwK&SsYcqz zC(s{6r@ceU+1UcJT8N}2-8;y_M$jKZA8vFfNEd1k(BnWDnp6CUNOh~Nbik@Yw`9nw zZJ`6n4~kYduqM_1FQ-3aRTD)*`&=8xPtqi2;ssWOB8#CB!Y2j^!DCiTW^ZQ8uQ9!KDxW|TzRBaE|m&Lu-hKapiV;Jj73Zn7{1q8*_5GH-SYk*5-KdVO!Oj* zb&!fcdb3hQ6<)OlXGmziw{7=_s%UJmVpHL5TbQ1jo>(bov{))sjYb^^xey~KhpKks zZYcc%Z?%O@q}w+)JL&CSv7^*ZO6yJNmho|WDtvcSxx#B+|H8(?_a^2u35Ltu<&~f3 zr9G8hV4IXlrd3Pl6dkjUHmq*o zyVsR`Q6wSWgXJ_ycj*?(s3WPmbl~===_&4;ZvL?_z1+hbM^P!O^>gooC)~GbU?MK?!RR8( zj)`&;cpQ8(Qg&Q~&>~i>(KDUI^#rQa2t)}ee3jA;=~nYaQ$m=!Svn`e4w9nTz8;GA z@)FX13ET=_LtfLf5KqhEvT$&UT%c@bk}jL1NC{`aIN22uG8kB0d)AP8DXEvPm<~;H zXh|uU&T;@MCy#s+LnJ$}qyT;GabRxbk~Z!}mP0;=O|Rbit94`3B9zPD9E~$!G>)Ug Mx%4Ak#_YuY55{@O#sB~S diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/hu/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/hu/LC_MESSAGES/ding.mo deleted file mode 100644 index a92afeeabbb56f43b5c2f2a664097c8311a34bf1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7163 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 F{{ZV)f$IPO diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/id/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/id/LC_MESSAGES/ding.mo deleted file mode 100644 index d2198dea4e008f0ed792c634cb8541e8d1458f13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2719 zcma)+&yN&E6vrQesH3Y03ixviL_x8KSQq+) zix*6kXkubwLgK-AG4agBcrfuIe}IVx@!-$12Q|ic;NbW5%~H>pMU!(Qa@f zxCh(-Ho)t_Hh44m0(c9kz!A`a_|aK(H-T@0EdMUZ>*qn1{|Kyr7eIFLGY~)e9Nj(O z7a-gF9_0PMfGqz9h##%NB)E0E*P!JXh+;4bh2 zxE=fk&hw{(^@||q z`Ad-Peg)nIUIN+PZy@`z9!bSt8UZ=Ko6)g70kXX+$o3us?*k8mocEVOt~(8~zvn>q z;{%ZM`U%K+y#($6FM|()+pwAQdlY2(MUd^h1|n7TI>`RK4RSp1fk<;%BkVW(!2YrC zypMed(D-{4jnCo{w4G>dpFj4Wb={A~wnx!+p>09qkL!bLZ}^GfACPnR5E{q8-`YOP zp5u8Kjn8o#8pp$D2$#zo0A(ypj*agf(m=b>_$*d`d{&%C{6lFwO?9mi zxjv(4TDnNlj6JD@w}ais)hW@m-6DlO;=!a%Lgi?-MYEYQWhb7~z9(jVPdRZU%M#s{ zUfaQ%HlhQEwUG(U$sD1~Ig1dyRyob9(4sRkRh)u00)+Q%g*5omL&PPZxAYHLapfRX zdF*W_G(69%5FfS2u4{@6)hw%^Hcsj4S)g_*lZ4tH6(n6q3kHc@Fe&QDbHceQf~hcg z7Lns<>cfzNGKV7NgK?F4m09P5nLN^A&?urj=-9fb%*_V#>ZIn4K@-JT7kg`CPXx97 z!PuA>+gE>l|L)rUTCFk-Edh$ox1x@hyH==P+`l|Qu5nG6oB$g%S$lnW+I*M_)Ib#Y)(`^xjd zQDv0tM>S_vsJ+-*-CNyPp{X<4#Bg;^CAj4U6i`EY6#K%W?BVKr=|n>%5;76j_?&Xu zcr1Ax%2+^?N((GfTP7NN3yA}>-r}`5CbJ@6zV6s*BI((J=*TqF2{yH0RXVmm1E(al zEDAf~aR(G_$Vof_agHjBMN^BmHhOs+m$z=dNFlQjmzs5qi`!7SbTp??OFh;Vt1Hws zZOrch-Y-{B|2^pc$D`0dEMMK{K^F!<-qj+5UH+`DV^p67kPPHS5 a2Zhts%kKr8i3O*frd1|$(UKYu3H=4$4wzp6 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/it/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/it/LC_MESSAGES/ding.mo deleted file mode 100644 index 29c81b1728b8895e4a40c93df57c3fff89fb2ae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9316 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ko/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ko/LC_MESSAGES/ding.mo deleted file mode 100644 index 5b21292da3294b707d73af9727b2e9f2fa4e2361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12592 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 aWX+?mT1lPeW@GjT~ zSHfX<2RsT_!zx?@UxfUW=W#pCp~$}s<@@VU$mWbb=%+u zScVesF(~U!Ly5x-yc6c|ZunYv{+%x0hho>qP~!I~6#1{A#N!7jc3y^P(-N<(!=7nHpv9y{n_Z?DPO_nPj#K#Aox`a|70sg+)PjF+8siQ`uKeRQ#1{1D%y zNvx&GS;+Zv3`JZdM|$m1UZgf8Po+uzs^K_J7W4_z_O+(-4K-qX&Bkh^X?(-#!=^UZ z$db0NUwZYN8cEVcHIi8qtQu(tHELrUtWIs#GT!Dvshs)%rS?h^6?a(O=l9XOpZL)NMW&l2ki9$P1ZH z4602+Jlgx{^${1dS22qZ~rB0V)rDpZxz`sXO9YRkm2ss`ihCabGyPk^U=i$yYgL^7Z5ECBT2iNq2KBxf7fO}5otZc~l4Px%tRufAvJTN8_CX__QqslKt-w~@v%EI zXUULMRa`A3jm)&LHVIVpQK2HIh_eaUU98pV(pKuEv+V_4U%E(S*ikk)cj0_-i?H_u zRZimKghZ$tHqC9pZP%44%BOpu%#%#SOjY8J>0=Imat^r&&SdIk7sb8j6U+T|{S8w@ zOG+WMiQAIHRpLfr=&pNup4??PgOF*@#HOD10)SQwDy!pH$NKP+9A03#n0#2y8_zuX zaNX3k0q!hAl8c#ri_7S$_!AJ_BvQ-v{14G`M^@G^AJ39MH&Xqd#miUa*Rs|k44o|D p|4YKTZ2OWFu~g%+b>wexd&%`RN!8S;2GUM)bJB;ogu^9&)!%wx+Drfd diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/oc/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/oc/LC_MESSAGES/ding.mo deleted file mode 100644 index 58626d1800db9842be53446e7af0034bcee58587..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15486 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/pt_BR/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/pt_BR/LC_MESSAGES/ding.mo deleted file mode 100644 index d25473491998c992d3f873e6191b9d5cd0edf862..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7573 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 MsB`Y9B^Woq1B6s&q5uE@ diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ro/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ro/LC_MESSAGES/ding.mo deleted file mode 100644 index f74ddfeceb9d62a2b37858b685f954174c333d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8856 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ru/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/ru/LC_MESSAGES/ding.mo deleted file mode 100644 index 453b87108f483480573160ec016ef3c626901ae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19747 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sk/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sk/LC_MESSAGES/ding.mo deleted file mode 100644 index 200538d72b2c759933253472bd010986214b1489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9109 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sv/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/sv/LC_MESSAGES/ding.mo deleted file mode 100644 index e6406e1a341df5243f73c33498b71600daadb5bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9956 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 ONBfcE?wSx==KleRQ=*9g diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/tr/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/tr/LC_MESSAGES/ding.mo deleted file mode 100644 index 837461d34928e17d052fe33302bb8107fe705a2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14894 zcmbW7dyr&ReaDZ0Afq4xi4W8qS8zdQdLIblEFd#Gvk&*l&LAv`dZ+u&%(c7kZSP~2 z9s(j75ll1*O7O)RC9Eb|vWY<|wJ}xptQ9q7s$#4>DpDqD{)m-m5~~s;mE`k1=ics~ z*+EFU_RP2Mx##gazxVm|K5_mTA2xhGOM5A;@oZzh2YzmZKYXq}*O+neb>JkJgQMV= zz^lOTgEjD?=Nt2j;2Xe;zyRC=-U0H@e1Sh_f`0;D34RrP4frIu4cu~`G0y|r;5p!O ziSH}%0g$cC!{7_SKLF1MzX4tVK2hSofzRdn%oiB*V(@%W`;CIye-8WwFaj?G-w9p@ zehAd~FN3ha{58lw^F)b124BVVX>58ico}#pxF6KGBcR^j3+@0P1;w}j0JYy%h&%(_ z1&WS+pw2T3ieGi`bnu-ZQ_QGzXX06)Ot^V;@3|=(fce8qjR4H>iq@a zi@?i3@oN&)_*+2ncLBTxEWpj+?}OUsd*CJDPeA^em#~;{6L>Z_1#12M{Ly|5a1QK% zmxJE|b!1|BpfK+XJ=kH$n07TcG6qQ&9Ynl4;!$@GS5mQ14#}YW}Oi zmw;D-JHdlx|AV09^=VLad>0fQXE69>;5nf5@Ny8=n`=SY>#>H9}Ojr$6yb$K>jndo<-UDi#?}C!Yk3rGpRF zHSedO&U*pMq4U;2>Cs;BR`70c3j8jpahIShXMxv)&jELVqWcC=atOfF!8<|m;cigp z`2eW%ejb#+`3fjHzYXgA{|su~Cqb=u28Yr63qe%FjDp&KFR1Ygpw?LeMc=)k{NFc0 z>BoP8@;?{QDZjG=l>BZ5N5BjeU3Y@w^C!R%{9W+1;CZ9oPwfKreh-Lf&CMm=35w2# zL9PEqQ2TxZ6d%72>O7~Rw9f-aK#pc!2x{B}cn)|Ah)B&Mcn0`EQ1pEW)V!mhZ-_vn2;`iC0A@d?qQ3{83;ro6`TZ3*4gLt!xvt#o_3L^Nl`>19 z_;eJ!7(50_E`J8f&;1aT{hiAnL~5=F#lI#fKEDSPJ)Z(Og833CKK~;qeK`*$;H$YD z)PA>udjDQf`#lQ6O7m?{{5t&#Pv1*G@&6#GbKVN-oL!KA=5GE>fscWxjQJVJ5@zFT zJil%MU%>ObKwOZyAG{F!L+}Fd>*ezkpw|6&P;z(@M0LzH7~vuqfsccK0e%*I|5aY@ zSE8hPzYTmo_%L`L_(f2BIthxeKL#a_{{+Rav#$2%y9Ctv-vr9O?gFJ(p9JM6zY2Z; zw6DWPz%PKfQA4-;+{E7p%kN={lCM6}SAE2{B^q0sduY|?<9rbh?xIN+@1$KryPkHC zHb;98?TxgL(3&)TK0`a~zF|M$0h(kdKd+DYcaHn!bw~Q}>onO#^%1Xj)80^aAU4yY zWwhU+ZKO$VGc@V#uhH~*wg;D6>g%Uzvt{3JgW@qN?mnL=QTia+OCI{1Mw5=cjV52D zPwc_vfM@glR+{|iJ7_PYNf#QlF6}L}7tti=kI|~nUcMZu9>AMvZ=$`Awu_e17HIFM zRiABqIiFUiJwlUie361PW(XOR+Xm6)|kQUMQ(57h87kxhI z{(3#tS5(;LY`25Ip$xqil$Fa+d`9F>+>tL!hJL5SHVlm z?-hKs`T_>DGt1}uz}skVE}x$ReyaR_sKgt=(`nD8eU^3$ZJhQx+IHG9ZTPd32TPMJ z-9Srd7t{24n0A!*TYBJg32l;gKMiv?`)MDb-9gi5AMHZ-&6s(xO*=+=7wz4&due9m znz`$y<6y28+N6_5Njz#dOtf0b5j%ZbSTFJ@Ua&hN-UgWs?7=iyNQ3r`&s*FR|g`+dF>A z{XsjtV}p${8;4;dY}k25PK8-BPdavYowdzGUG&*Jv5mwYSqx*_3W~VCC=vr(u4CuZ zq-`Ohb`R#bcX4>c zHqvM*%(R8}Pdc3>i}KKB>|>L8*O}GRFpQ1o@ZO4io{t1wPUyfk!>~NFok-IlUVt5Q zT{piKWVsEh&LnMw={mD!@}S-f8>4n6YDcXgwRyJ#VL=+&g)}KTVZ%(sZtboJ%kmT+ zLbyha+NmVom|M4o_RPX^IwR-N1jtNb`ci0PWX6M|&`x%1HMmzkl@cqT4tP4VCSnV6 zFF`X=Q&Ae$^Ca!|-y|L8=ZmPEQ}DU49uyolf*9#~x!6p%Ee+7Dde|xf zI-#xINl|cg(rjOplG&}>iI?I3Qr^UP~`*TYiSV<$}W2%#{h6XcN$`AC#6O3P8f zFr^Rs$huh`woz{l6V>+i&38C)p4#Kr8VpKW(z4YPUEg4!wkQd%xKi~XSqx(1#kVI# z-YIgi`i_nL)%p|H9cCBtI&&C|tvl|E?WG|gsdR9fXS@v5wZc4X3{8cN^{N}XIw(jQ z202`JfYmr{_mA2L#{y5`D>LUy<`lV^Lcmx%EJs#Iyw#;^$bTX1T(Zc_RFrjELHE=S zxeZ)hE`2E-hPZ0HMXq%kQ%NCd*QGpW`t4|!nQnLTuANPTY|%`!PAbP3WZ4lsg~cg{ zW;#uAtc^kzzetK*CdI>+R=$_%^ zN;0c<^Qtzqg6mkLLZSstt42x8l@hJ$tadOW-21d05yqy+%rdQ%qS@hOU5&UMTa zfuspRD}wWAI;?I&Nj1yIu2I`f3fnGl-le0nr-r^*gVNGeYi1YTuH`(Qi)L85MQiE= zHZQ!XG+5XeZ=B+V*_Ggl<#P!(%l;ejw+a)^WbkQ(NO_B{*&Q!IZ(}%e4;|E<-0V>h zs+N$nU5E4Q{qEtuGUoWM^1&G^K}FN|2I)e`Uqx&e$|SSuxyYnMQ(+^jV|fj`GYvY6 zQ9ZNUgS27xCiS4@{R?DbSNjs854`q@zCR#MX%(d#-xtKe0*Wu+?|tR|a0&kKjn+ey@`~P;AEqPxWA(BBaWs0D0N_uIY5|ke=G)UZ<23z z36h=YbTD1#N5mkF(~$o6^@sX#DA=shF7(bE3~;fIrLABtY}q`#O=@Q6&=#p8o}cs! ze{y7zgVpSfS%|Ir49YX!tJz#XdJ!iM;x#&pIFit&;X4X~r%%bSbL6JTe}@|*&(i-Q z4a@OEjIAw4ol&pxbHvmtx=YP&!n%?pFb^Z!7u4NexZ9yvb|`El=1|y9mZTOP_!*T7 za7rLK0GA*}S6@pHA&ag2dihEoK8owD0+&CW zLX7r3r(=7gN-d<5fm2leq*-2L9S)g0Z>dz-J9y1m_dV@Z#pWF+RRjfyQQwq7N}V$^?Lc;N##GYR#e?mC-pv!`b=J#89R4fo>zRCa2IYX|IfMw~H?O zch=l0K6CbdWlbVY1R_gqbZvNBl;!wsM@S8S3lpsvSv{Q0JmtUT#^(iwVi|zXJrhSfNhBXE^mGV!F z&5eXx{x}Z`vM*`DKw(J-?0#Y`j-j6^^!1j7$Qi494*Jy}z2=R3;WG|ZZU&i%dx1f4 zzb*3;g)2WGGdHP>6EtLFmD5#PP6fIu4#~yw{#o19{L+aR!h=_TAmIjjAObZ`*!b}9-LuI zZS%->e>)zNx-$fg+64Eac$);6;xDefadyYp)q`;&cRozVrg4B`!nnP9F3Lv^wu&@p zjqOO%b~bL~j(g0m-Lef~=*_j8w~gF9wlgGC^JhJnIOljpZEJ1oh%0?=m`bv45U(6} zWf(aldw^P7(6onpC(_=Dymz8Sh7!f0U3qjF=^~5`$gOvbRacHiab&~18O5#ekwmuq)~vn_~^?tDc0Q z8>Fqkt$4~sb6=1Jy%QPqsXn+sDu)zV01~-4g-vdTQECRGVx?(B*9B;RRHnfS%m@%0f)8?Ds zKk!9bXb5X&a(IEj4!s*}qS74n<8ucy&2$r~OD@eIJ$ck^od)xC1hyN(_RPtrj(p&( z_F}7((3(5a`oc1lJnS;`#^gg4pGX=l=R`$#VH>>@%d7|o7J83CMI#`WEqhy$%_$2F zrjqOXyoAZLCVhRC1g+e!*IPV^*k!DA^D*hM)I1HEG%*Z9?sw<-kQ#y>=Db$%w)f$Ag>U7*043 z#8tE}C8o8*Wy-+I1$xD>8LIh7D{4}4t&|LvY7{F+xuZBuo-6z=Hs~Fb2Ex!TXIOc( zL)f*`$Ytetvr=RZ&lQn=Y`oQoU|y5oIuHXVpVB#->IB9I~8w-1@ix2J%_pY zoES5xtrhvuJH*kE8JPnuoL63;?B0I3W%}n`{3tbVOMaqjz8mq0V|&8P%xWjR;S5GG z(Doq@JKr8(=H1?EN<&xEoCm-@# zl+QAdQwzbeKgj#PNc(9P84}z;Gl)!XpGqV93OPDZM_&@Q%_JsB5e?Q(DbKOi9SpjM zcJ}Lg2Ro2A-l`ed%7Rd7EZpqzR_Mp#xSdH;+OmUr13h7devtJ%^A63MKUo6>pi@FR zKAEfa%5jNt<@j>V%s5|z7qL`ICnaHm?U117To(uJqI0;kr6OG@(EsTrAF%9P(k=4B zKPWEYPkpefLY-U9Th_3?yQA~Y=REROb{9$oZN|qJ!s2X^uZ~5-Z~9wCwhU;@)fBly zLadA@T=Pn+P4-T7dncM$!5~2~&YP;5JWs6HLmiQ&yu)#c+MG8qm}U+KEpe{yI6@J% zQN~qoRiT|_C}-$jjNE(MB|hPt>x5)DH1OpUq{u#2OolDW-Y#sEYTz7m?=gZpVa+Eb zrCagCGKFZn7%jUL16B@oi=PyB9og~1%JJT@GVo@RcR*&Mcg)3&-icVQfRTi<8@m!N z*$qB`0b-Y8iyu>VtUuJ;=o8B}TB)U{^Qg(CydCCbJ)Al02FqTD^gDMqSj68X-Jqty zm?PH`^0SD_5L76y>AQQEIaa=(5Vvw17foGlsJ>iA^2&Gl)RbDYTv-X2a#}deFAL69 zZ5genv}~2pz%ht-S&JL#_c^SL)u*vuOUjsgnDm3-O=6M}%e|D>hO;ap?TqC3C0Av~ z6Af<(>-5Memc@!HIUmlU%_REcqP_BmA+fl}f#-4YM=W>!KG$%ro%|4$z(;UUNE)@M zq<$n)Hv&>lB~>O6pi2Gh0F|#P4k^1@Ws6GZsTp&oh#!-6w=7jL9?Aw;joU?S*zTRy zI`x!-I_E*XxEeU&W8c7hr1~A{qpS+yOEvsppZ0jwoGOj*>nDg!Q0t=Nz-dau*Bw&D zVg%I=tGk8n8ZKy(S7!be*6fGcT|tT!ueupT+|a9wk~Ciy(&hT7a14Xr#OU5Xv#r&7u+JZ z>8CjHDN9zzo!UROD)KG5M2@g0hPxX_vq4D77tr)_4!7S~)TWPCqNcU%?TRcPnO-0JsV=jc|&SKI@LFYaF?fbF#_|-299$YaRYFRk7GE1;i&vsa4f=XVQ!pKZf!hibB}b$)mO5 z%N!oVU9aUCDv#tY%d>c8{xb+mP~J=lP8>=#_u-8y!m1QqS2w8P2&(?b(>qz}v~2E< zSk`NJ%Vi)XWOKD8Jk*AYQ@T@^mG`M+R8<<_Qm-12*!JU3Mb7viF-wi)GT)*GCP%6PqerqszO6*+frI1r70KT{|C5{ zijmdZVY?4hlBg81Z$a)hQ2rd?lQX=(zr8pOTRlrZ8u(GG^1?E2bLn99e#RxWN_E0q zE4h>m^H(NG!ceXM$NaF_xB diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/uk/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/uk/LC_MESSAGES/ding.mo deleted file mode 100644 index 5e3ff870a6aeb80f2d2e710ca86604bdc563ae05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19334 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 N5ZhUDOJ@Di{{eQGTB`s6 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_CN/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_CN/LC_MESSAGES/ding.mo deleted file mode 100644 index 1cdf773bb45ef00d3e11e0f4ed86b8d7da720b31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11226 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 diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_TW/LC_MESSAGES/ding.mo b/.local/share/gnome-shell/extensions/ding@rastersoft.com/locale/zh_TW/LC_MESSAGES/ding.mo deleted file mode 100644 index f3407509f07d37a7792204fb0f3ba33072257158..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5963 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 Ee;H>yz5oCK diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/metadata.json b/.local/share/gnome-shell/extensions/ding@rastersoft.com/metadata.json deleted file mode 100644 index 6a610fd..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Adds icons to the desktop. Fork of the original Desktop Icons extension, with several enhancements .", - "name": "Desktop Icons NG (DING)", - "shell-version": [ - "45" - ], - "url": "https://gitlab.com/rastersoft/desktop-icons-ng", - "uuid": "ding@rastersoft.com", - "version": 65 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/prefs.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/prefs.js deleted file mode 100644 index 48289b6..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/prefs.js +++ /dev/null @@ -1,39 +0,0 @@ - -/* Desktop Icons GNOME Shell extension - * - * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) - * - * 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 . - */ -'use strict'; -import Gio from 'gi://Gio' -import Adw from 'gi://Adw'; - -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class DingPreferences extends ExtensionPreferences { - fillPreferencesWindow(window) { - let mainAppControl = Gio.DBusActionGroup.get( - Gio.DBus.session, - 'com.rastersoft.ding', - '/com/rastersoft/ding' - ); - mainAppControl.activate_action('changeDesktopIconSettings', null); - - const page = new Adw.PreferencesPage(); - - window.add(page); - window.connect_after('show', ()=>{window.destroy();}); - } -} diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/gschemas.compiled deleted file mode 100644 index 0bdac87102a35ad2b63f7e0050d73e41da447c59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1445 zcmZWp&1(}u9GzNYzdy7JMGq<>B+yM-5d5GAYg60MHXf>_76rG-G+DCQS#~!~>qk$5 z9@Lv4=s{4i7r}!d6ouaG#fyJ{=*5c{KTr^a^}X3mdvM_8y?ry2`OWY5W5#Dq&oZ4r z#G@ZP7wP1Vh6zsW6C%Wj=BD(TOYo1ro_)k+)Ca|cxDI}RjZI+XmC_|gRb|>QOWRJ% zVr5rz9w44%Fh-4psF}R-RH3K_=7N8Ai2RebS7~S9odZ2q_>;V&p2ArP>Fk|Qy zOJWWD0{C)j|4sVTd*N?_-vgeM7mf@~uGPEDk;I2c{Po z1?4%?i);}n*RbWH?(fFhaN7*oclz72O65R=D8C37R1m0YV_%4pZF$i$5w?k>pIk9( zsg#bi=;0jKHVch2qIh_Tz%%`F6d(SF=dq{RtL*Dtz;1xO&U4t$9PEFT2)!pnE5Nuq z0QSCBP>$hSS9un$>=aF}2r2ljV+|~41tHT5{i~X>6PSvcX4D;S6-!& zY5ofb^6x98*LP*XGHqi~*+uF3(PT7VkWl;^L&t-FGb7R@_Ic^S_pKvml&w>)vGr4*CiLKhyoH&|b z#g$R0Nz+duVHG35b7WYKVVeum#vI~IyJk?vA7NzhcxCkCmC=t^X8ZBV@bStZ^)+7_ yj;yL^2lK;v#|;{pabMCe;~|XuROcy9%2uMVzfhKiim^O2R5w>_)D{1s`{*ACNG^N; diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/org.gnome.shell.extensions.ding.gschema.xml b/.local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/org.gnome.shell.extensions.ding.gschema.xml deleted file mode 100644 index d29f569..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/schemas/org.gnome.shell.extensions.ding.gschema.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - 'standard' - Icon size - Set the size for the desktop icons. - - - true - Show personal folder - Show the personal folder in the desktop. - - - true - Show trash icon - Show the trash icon in the desktop. - - - 'top-left' - New icons start corner - Set the corner from where the icons will start to be placed. - - - true - Show external drives in the desktop - Show the disk drives connected to the computer. - - - false - Show network drives in the desktop - Show mounted network volumes in the desktop. - - - true - Add new drives to the opposite side of the screen - When adding drives and volumes to the desktop, add them to the opposite side of the screen. - - - true - Shows a rectangle in the destination place during DnD - When doing a Drag'n'Drop operation, marks the place in the grid where the icon will be put with a semitransparent rectangle. - - - false - Sort Special Folders - Home/Trash Drives. - When arranging Icons on desktop, to sort and change the position of the Home, Trash and mounted Network or External Drives - - - false - Keep Icons Arranged - Always keep Icons Arranged by the last arranged order - - - 'NAME' - Arrange Order - Icons Arranged by this property - - - false - Keep Icons Stacked - Always keep Icons Stacked, Similar types are grouped - - - [] - Type of Files to not Stack - An Array of strings types, Don't Stack these types of files - - - false - Use Nemo to open folders - Use Nemo instead of Nautilus to open folders. - - - true - Add an emblem to links - Add an emblem to allow to identify soft links. - - - false - Use black for label text - Paint the label text in black instead of white. Useful when using light backgrounds. - - - true - Show a popup if running on X11Wayland - Whether DING should show a popup if it is running on X11Wayland, or the user decided to not show it anymore. - - - diff --git a/.local/share/gnome-shell/extensions/ding@rastersoft.com/visibleArea.js b/.local/share/gnome-shell/extensions/ding@rastersoft.com/visibleArea.js deleted file mode 100644 index c5119ed..0000000 --- a/.local/share/gnome-shell/extensions/ding@rastersoft.com/visibleArea.js +++ /dev/null @@ -1,146 +0,0 @@ -/* DING: Desktop Icons New Generation for GNOME Shell - * - * Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com) - * - * 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, version 3 of the License. - * - * 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 . - */ -'use strict'; -const Signals = imports.signals; -import * as Main from 'resource:///org/gnome/shell/ui/main.js' -import GLib from 'gi://GLib' - -export class VisibleArea { - constructor() { - this._usableAreas = {}; - this._marginsList = {}; - this._refreshTimerId = null; - // This UUID allows to ensure that the object is really a DesktopIconsIntegration object - this._extensionUUID = '130cbc66-235c-4bd6-8571-98d2d8bba5e2'; - } - - disable() { - if (this._refreshTimerId !== null) { - GLib.source_remove(this._refreshTimerId); - this._refreshTimerId = null; - } - } - - setMarginsForExtension(extensionUUID, margins) { - if (margins == null) { - if (!(extensionUUID in this._marginsList)) { - return; - } - delete this._marginsList[extensionUUID]; - } else { - this._marginsList[extensionUUID] = margins; - } - if (this._refreshTimerId) { - GLib.source_remove(this._refreshTimerId); - } - this._refreshTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { - this._refreshMargins(); - this._refreshTimerId = null; - return GLib.SOURCE_REMOVE; - }); - } - - _refreshMargins() { - this._usableAreas = {}; - for (let extensionUUID in this._marginsList) { - let margins = this._marginsList[extensionUUID]; - for (let workspace in margins) { - let index = workspace; - if (workspace < 0) { - index = Main.layoutManager.primaryIndex; - } - if (!(index in this._usableAreas)) { - this._usableAreas[index] = { - top: 0, - bottom: 0, - left: 0, - right: 0, - }; - } - for (let index2 of ['top', 'bottom', 'left', 'right']) { - this._usableAreas[index][index2] = Math.max(this._usableAreas[index][index2], margins[workspace][index2]); - } - } - } - this.emit('updated-usable-area'); - } - - /** - * Returns the margin values for an specific monitor - * - * @param {} ws A workspace (obtained with global.workspace_manager.get_workspace_by_index(0);) - * @param {*} monitorIndex The monitor number - * @returns A dictionary with the following elements: - * x: the X coordinate of the monitor area - * y: the Y coordinate of the monitor area - * width: the width of the monitor area - * height: the height of the monitor area - * scale: the scale factor for this monitor - * marginTop: the number of pixels, counting from the top of the monitor, to leave free because are used by a dynamic element - * marginBottom: the number of pixels, counting from the bottom of the monitor, to leave free because are used by a dynamic element - * marginLeft: the number of pixels, counting from the left of the monitor area, to leave free because are used by a dynamic element - * marginRight: the number of pixels, counting from the right of the monitor area, to leave free because are used by a dynamic element - * - * The inner margins so returned automatically describe the working area of the monitor (in Gnome terms) that for example the top margin will - * automatically include the height of the top panel. - * - * In addition any extra margins above that set by gnome by othe extensions in usable areas will be returned if they are bigger than the margins - * described by gnome shell for the work area - * - * Thus, a window that covers the whole monitor area should be placed at X,Y and with a size of (width, height), and - * it must have inner margins of marginTop, marginRight, marginBottom and marginLeft. - */ - - getMonitorGeometry(ws, monitorIndex) { - let geometry = ws.get_display().get_monitor_geometry(monitorIndex); - let scale = ws.get_display().get_monitor_scale(monitorIndex); - let area = ws.get_work_area_for_monitor(monitorIndex); - - // calculate the margins due to the difference between the monitor geometry and the work area, ie. the work area margins - let marginTop = area.y - geometry.y; - let marginLeft = area.x - geometry.x; - let marginRight = geometry.width - area.width - marginLeft; - let marginBottom = geometry.height - area.height - marginTop; - - if (monitorIndex in this._usableAreas) { - // If the margins for this monitor are bigger than the margins calculated previously, - // use the higher number. This is because the margin set from the extensions are be from the monitor border, - // an can supersede the ones that actually form the work area border. - marginTop = Math.max(marginTop, this._usableAreas[monitorIndex]['top']); - marginBottom = Math.max(marginBottom, this._usableAreas[monitorIndex]['bottom']); - marginLeft = Math.max(marginLeft, this._usableAreas[monitorIndex]['left']); - marginRight = Math.max(marginRight, this._usableAreas[monitorIndex]['right']); - } - - return { - x: geometry.x, - y: geometry.y, - width: geometry.width, - height: geometry.height, - scale, - marginTop, - marginBottom, - marginLeft, - marginRight, - }; - } - - get uuid() { - return this._extensionUUID; - } -}; -Signals.addSignalMethods(VisibleArea.prototype); diff --git a/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/extension.js b/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/extension.js deleted file mode 100644 index fc06eaf..0000000 --- a/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/extension.js +++ /dev/null @@ -1,68 +0,0 @@ -/* 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 Extension */ -import Gio from 'gi://Gio'; - -const DEFAULT_SCHEME_NAME = 'default'; -const LIGHT_SCHEME_NAME = 'prefer-light'; -const DARK_SCHEME_NAME = 'prefer-dark'; - -export default class LegacyThemeSchemeAutoSwitcher { - handleThemeChange = (theme_name) => { - switch(theme_name) - { - case DEFAULT_SCHEME_NAME: - case LIGHT_SCHEME_NAME: - if (this.schema.get_string('gtk-theme').endsWith("-dark")) { - this.schema.set_string('gtk-theme', this.schema.get_string('gtk-theme').slice(0,-5)); - } - break; - case DARK_SCHEME_NAME: - if (!this.schema.get_string('gtk-theme').endsWith("-dark")) { - this.schema.set_string('gtk-theme', this.schema.get_string('gtk-theme') + "-dark"); - } - break; - default: - break; - } - } - - handleCurrentTheme = () => { - let value = this.schema.get_string('color-scheme'); - this.handleThemeChange(value); - } - - enable() { - this.schema = Gio.Settings.new('org.gnome.desktop.interface'); - this.id = this.schema.connect('changed::color-scheme', () => { - this.handleCurrentTheme(); - }); - this.handleCurrentTheme(); - } - - disable() { - if (this.schema) { - if (this.id) { - this.schema.disconnect(this.id); - this.id = null; - } - this.schema = null; - } - } -} diff --git a/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/metadata.json b/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/metadata.json deleted file mode 100644 index 8c3fb61..0000000 --- a/.local/share/gnome-shell/extensions/legacyschemeautoswitcher@joshimukul29.gmail.com/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Change the GTK3 theme to light/dark variant based on the system color scheme", - "name": "Legacy (GTK3) Theme Scheme Auto Switcher", - "shell-version": [ - "45" - ], - "url": "https://github.com/mukul29/legacy-theme-auto-switcher-gnome-extension", - "uuid": "legacyschemeautoswitcher@joshimukul29.gmail.com", - "version": 7 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/LICENSE b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/LICENSE deleted file mode 100644 index f288702..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - 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/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/extension.js b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/extension.js deleted file mode 100644 index 0d914fd..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/extension.js +++ /dev/null @@ -1,209 +0,0 @@ -/* 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 - */ - -import Clutter from 'gi://Clutter'; - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { MediaSection } from 'resource:///org/gnome/shell/ui/mpris.js'; - -import { LibPanel, Panel } from './libs/libpanel/main.js'; -import { ApplicationsMixer, waitProperty } from './libs/widgets.js'; - -const DateMenu = Main.panel.statusArea.dateMenu; -const QuickSettings = Main.panel.statusArea.quickSettings; - -const CalendarMessageList = DateMenu._messageList; -const MediaSection_DateMenu = CalendarMessageList._mediaSection; - -const SystemItem = QuickSettings._system._systemItem; -// _volumeOutput is always defined here because `./libs/widgets.js` wait on it -const OutputVolumeSlider = QuickSettings._volumeOutput._output; - -export default class QSAP extends Extension { - async enable() { - this.InputVolumeIndicator = await waitProperty(QuickSettings, '_volumeInput'); - this.InputVolumeSlider = this.InputVolumeIndicator._input; - - this.settings = this.getSettings(); - - this._scasis_callback = this.settings.connect( - 'changed::always-show-input-slider', - () => this._set_always_show_input(this.settings.get_boolean('always-show-input-slider')) - ); - this.settings.emit('changed::always-show-input-slider', 'always-show-input-slider'); - - this._master_volumes = []; - this._sc_callback = this.settings.connect('changed', () => this._refresh_panel()); - this._refresh_panel(); - } - - disable() { - this.settings.disconnect(this._scasis_callback); - this.settings.disconnect(this._sc_callback); - for (const id of waitProperty.idle_ids) { - GLib.Source.remove(id); - } - waitProperty.idle_ids = null; - - this._set_always_show_input(false); - this._cleanup_panel(); - - this.settings = null; - } - - _refresh_panel() { - this._cleanup_panel(); - - const move_master_volume = this.settings.get_boolean('move-master-volume'); - const media_control_action = this.settings.get_string('media-control'); - const create_mixer_sliders = this.settings.get_boolean('create-mixer-sliders'); - const merge_panel = this.settings.get_boolean('merge-panel'); - const panel_position = this.settings.get_string("panel-position"); - const widgets_ordering = this.settings.get_strv('ordering'); - - const filter_mode = this.settings.get_string('filter-mode'); - const filters = this.settings.get_strv('filters'); - - if (move_master_volume || media_control_action !== 'none' || create_mixer_sliders) { - LibPanel.enable(); - - this._panel = LibPanel.main_panel; - let index = -1; - - if (!merge_panel) { - this._panel = new Panel('main'); - // Since the panel contains no element that have a minimal width (like QuickToggle) - // we need to force it to take the same with as a normal panel - this._panel.add_constraint(new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.WIDTH, - source: LibPanel.main_panel, - })); - - LibPanel.addPanel(this._panel); - - } - if (merge_panel && panel_position === 'top') { - widgets_ordering.reverse(); - index = this._panel.getItems().indexOf(SystemItem) + 2; - } - - for (const widget of widgets_ordering) { - if (widget === 'volume-output' && move_master_volume) { - this._move_slider(index, OutputVolumeSlider); - } else if (widget === 'volume-input' && move_master_volume) { - this._move_slider(index, this.InputVolumeSlider); - } else if (widget === 'media' && media_control_action === 'move') { - this._move_media_controls(index); - } else if (widget === 'media' && media_control_action === 'duplicate') { - this._create_media_controls(index); - } else if (widget === 'mixer' && create_mixer_sliders) { - this._create_app_mixer(index, filter_mode, filters); - } - } - } - } - - _cleanup_panel() { - if (!this._panel) return; - - if (this._applications_mixer) { - this._applications_mixer.destroy(); - this._applications_mixer = null; - } - - if (this._media_section) { - this._panel.removeItem(this._media_section); - this._media_section = null; - } - if (MediaSection_DateMenu.has_style_class_name('QSAP-media-section')) { - this._panel.removeItem(MediaSection_DateMenu); - CalendarMessageList._sectionList.insert_child_at_index(MediaSection_DateMenu, 0); - MediaSection_DateMenu.remove_style_class_name('QSAP-media-section'); - } - - this._master_volumes.reverse(); - for (const [slider, index] of this._master_volumes) { - this._panel.removeItem(slider); - LibPanel.main_panel.addItem(slider, 2); - LibPanel.main_panel._grid.set_child_at_index(slider, index); - } - this._master_volumes = []; - - if (this._panel !== LibPanel.main_panel) { - LibPanel.removePanel(this._panel); // prevent the panel's position being forgotten - this._panel.destroy(); - }; - this._panel = null; - - LibPanel.disable(); - } - - _move_slider(index, slider) { - const old_index = slider.get_parent().get_children().indexOf(slider); - - LibPanel.main_panel.removeItem(slider); - this._panel.addItem(slider, 2); - this._panel._grid.set_child_at_index(slider, index); - - this._master_volumes.push([slider, old_index]); - } - - _move_media_controls(index) { - CalendarMessageList._sectionList.remove_child(MediaSection_DateMenu); - - this._panel.addItem(MediaSection_DateMenu, 2); - this._panel._grid.set_child_at_index(MediaSection_DateMenu, index); - - MediaSection_DateMenu.add_style_class_name('QSAP-media-section'); - } - - _create_media_controls(index) { - this._media_section = new MediaSection(); - this._media_section.add_style_class_name('QSAP-media-section'); - - this._panel.addItem(this._media_section, 2); - this._panel._grid.set_child_at_index(this._media_section, index); - } - - _create_app_mixer(index, filter_mode, filters) { - this._applications_mixer = new ApplicationsMixer(this._panel, index, filter_mode, filters); - } - - _set_always_show_input(enabled) { - if (enabled) { - this._ivssa_callback = this.InputVolumeSlider._control.connect('stream-added', () => { - this.InputVolumeSlider.visible = true; - this.InputVolumeIndicator.visible = this.InputVolumeSlider._shouldBeVisible(); - }); - this._ivssr_callback = this.InputVolumeSlider._control.connect('stream-removed', () => { - this.InputVolumeSlider.visible = true; - this.InputVolumeIndicator.visible = this.InputVolumeSlider._shouldBeVisible(); - }); - this.InputVolumeSlider.visible = true; - this.InputVolumeIndicator.visible = this.InputVolumeSlider._shouldBeVisible(); - } else { - if (this._ivssr_callback) this.InputVolumeSlider._control.disconnect(this._ivssr_callback); - if (this._ivssa_callback) this.InputVolumeSlider._control.disconnect(this._ivssa_callback); - this._ivssr_callback = null; - this._ivssa_callback = null; - this.InputVolumeSlider.visible = this.InputVolumeSlider._shouldBeVisible(); - this.InputVolumeIndicator.visible = this.InputVolumeSlider._shouldBeVisible(); - } - } -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/LICENSE b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/LICENSE deleted file mode 100644 index f288702..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - 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/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/README.md b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/README.md deleted file mode 100644 index 18a88d6..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/README.md +++ /dev/null @@ -1 +0,0 @@ -You can find informations and instructions [here](https://github.com/Rayzeq/libpanel/wiki). \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/gschemas.compiled b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/gschemas.compiled deleted file mode 100644 index 09c25d98f0bed0867833b8701ef73c2ca435dd00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 632 zcmY*WJxjw-6uo}5RVylfA%ajSLOL{Y^dIQZ!A0qy!%G|5K>8Az)DKW`@CP`Ge?S)} z7e@yN5y8R1wWHvmgP@z96C2uIIPaXCck}M$-nA{&bd`>z6AR$-zcvOt-T?T~x2MRw z%geePf=^(i=0tuGQJh>7@;=}t`^t{o`tcz8jKQJx6? zJ_HN{DIg7Gdhqca?2O=>HM6oSXW(;SHh20;pL!Dh75EysJ37v?FX|NhTW}k2UhdzR zPdx$u6Z`|@Z{Ek~Q>Wpxp)|0R`)<>xo`;_UF9X|84;S>QGw@fytH5RYYmq+n4Ezo7 zCXmdDTBIapFlW{D_ljYlDz2{aLdJO*ZXr833k#9>rV4Pe?5Kor!yZZ+$HzO NeR7u=YaHAu;}7fofe8Qr diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/main.js b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/main.js deleted file mode 100644 index 1712685..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/main.js +++ /dev/null @@ -1,953 +0,0 @@ -// Documentation: https://github.com/Rayzeq/libpanel/wiki -// Useful links: -// - Drag & Drop example: https://gitlab.com/justperfection.channel/how-to-create-a-gnome-shell-extension/-/blob/master/example11%40example11.com/extension.js - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import { BoxPointer } from 'resource:///org/gnome/shell/ui/boxpointer.js'; -import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { PopupMenu } from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import { QuickSettingsMenu } from 'resource:///org/gnome/shell/ui/quickSettings.js'; - -import { Patcher } from './patcher.js'; -import { - add_named_connections, - array_insert, - array_remove, - find_panel, - get_extension_uuid, - get_settings, - rsplit, - set_style, - split -} from './utils.js'; - -const MenuManager = Main.panel.menuManager; -const QuickSettings = Main.panel.statusArea.quickSettings; -const QuickSettingsLayout = QuickSettings.menu._grid.layout_manager.constructor; - -const VERSION = 1; -// The spacing between elements of the grid, in pixels. -const GRID_SPACING = 5; - -function registerClass(metadata, klass) { - if (klass === undefined) { - klass = metadata; - metadata = {}; - } - - metadata.GTypeName = `${metadata.GTypeName || `LibPanel_${klass.name}`}_${get_extension_uuid().replace(/[^A-Za-z_-]/g, '-')}`; - - return GObject.registerClass(metadata, klass); -} - -const AutoHidable = superclass => { - // We need to cache the created classes or else we would register the same class name multiple times - if (AutoHidable.cache === undefined) AutoHidable.cache = {}; - if (AutoHidable.cache[superclass.name] !== undefined) return AutoHidable.cache[superclass.name]; - - const klass = registerClass({ - GTypeName: `LibPanel_AutoHidable_${superclass.name}`, - }, class extends superclass { - constructor(...args) { - const container = args.at(-1).container; - delete args.at(-1).container; - super(...args); - - // We need to accept `null` as valid value here - // which is why we don't do `container || this` - this.container = container === undefined ? this : container; - } - - get container() { - return this._lpah_container; - } - - set container(value) { - if (this._lpah_container !== undefined) this.disconnect_named(this._lpah_container); - if (value !== null) { - this._lpah_container = value; - this.connect_named(this._lpah_container, 'actor-added', (_container, children) => { - this.connect_named(children, 'notify::visible', this._update_visibility.bind(this)); - this._update_visibility(); - }); - this.connect_named(this._lpah_container, 'actor-removed', (_container, children) => { - this.disconnect_named(children); - this._update_visibility(); - }); - this._update_visibility(); - } - } - - _get_ah_children() { - return this._lpah_container.get_children(); - } - - _update_visibility() { - for (const child of this._get_ah_children()) { - if (child.visible) { - this.show(); - return; - } - } - - this.hide(); - // Force the widget to take no space when hidden (this fixes some bugs but I don't know why) - this.queue_relayout(); - } - }); - AutoHidable.cache[superclass.name] = klass; - return klass; -}; - -const Semitransparent = superclass => { - // We need to cache the created classes or else we would register the same class name multiple times - if (Semitransparent.cache === undefined) Semitransparent.cache = {}; - if (Semitransparent.cache[superclass.name] !== undefined) return Semitransparent.cache[superclass.name]; - - const klass = registerClass({ - GTypeName: `LibPanel_Semitransparent_${superclass.name}`, - Properties: { - 'transparent': GObject.ParamSpec.boolean( - 'transparent', - 'Transparent', - 'Whether this widget is transparent to pointer events', - GObject.ParamFlags.READWRITE, - true - ), - }, - }, class extends superclass { - get transparent() { - if (this._transparent === undefined) - this._transparent = true; - - return this._transparent; - } - - set transparent(value) { - this._transparent = value; - this.notify('transparent'); - } - - vfunc_pick(context) { - if (!this.transparent) { - super.vfunc_pick(context); - } - for (const child of this.get_children()) { - child.pick(context); - } - } - }); - Semitransparent.cache[superclass.name] = klass; - return klass; -}; - -const GridItem = superclass => { - // We need to cache the created classes or else we would register the same class name multiple times - if (GridItem.cache === undefined) GridItem.cache = {}; - if (GridItem.cache[superclass.name] !== undefined) return GridItem.cache[superclass.name]; - - const klass = registerClass({ - GTypeName: `LibPanel_GridItem_${superclass.name}`, - Properties: { - 'draggable': GObject.ParamSpec.boolean( - 'draggable', - 'draggable', - 'Whether this widget can be dragged', - GObject.ParamFlags.READWRITE, - true - ), - }, - }, class extends superclass { - constructor(panel_name, ...args) { - super(...args); - - this.is_grid_item = true; - this.panel_name = panel_name; - - this._drag_handle = DND.makeDraggable(this); - this.connect_named(this._drag_handle, 'drag-begin', () => { - QuickSettings.menu.transparent = false; - - // Prevent the first column from disapearing if it only contains `this` - const column = this.get_parent(); - this._source_column = column; - if (column.get_next_sibling() === null && column.get_children().length === 1) { - column._width_constraint.source = this; - column._inhibit_constraint_update = true; - } - - this._dnd_placeholder?.destroy(); - this._dnd_placeholder = new DropZone(this); - - this._drag_monitor = { - dragMotion: this._on_drag_motion.bind(this), - }; - DND.addDragMonitor(this._drag_monitor); - - this._drag_orig_index = this.get_parent().get_children().indexOf(this); - // dirty fix for Catppuccin theme (because it relys on CSS inheriting) - // this may not work with custom grid items - this.add_style_class_name?.("popup-menu"); - }); - // This is emited BEFORE drag-end, which means that this._dnd_placeholder is still available - this.connect_named(this._drag_handle, 'drag-cancelled', () => { - // This stop the dnd system from doing anything with `this`, we want to manage ourselves what to do. - this._drag_handle._dragState = DND.DragState.CANCELLED; - - if (this._dnd_placeholder.get_parent() !== null) { - this._dnd_placeholder.acceptDrop(this); - } else { // We manually reset the position of the panel because the dnd system will set it at the end of the column - this.get_parent().remove_child(this); - this._drag_handle._dragOrigParent.insert_child_at_index(this, this._drag_orig_index); - } - }); - // This is called when the drag ends with a drop and when it's cancelled - this.connect_named(this._drag_handle, 'drag-end', (_drag_handle, _time, _cancelled) => { - QuickSettings.menu.transparent = true; - - if (this._drag_monitor !== undefined) { - DND.removeDragMonitor(this._drag_monitor); - this._drag_monitor = undefined; - } - - this._dnd_placeholder?.destroy(); - this._dnd_placeholder = null; - - const column = this._source_column; - if (!column._is_destroyed && column._width_constraint.source == this) { - column._width_constraint.source = column.get_next_sibling(); - column._inhibit_constraint_update = false; - } - - // Something, somewhere is setting a forced width & height for this actor, - // so we undo that - this.width = -1; - this.height = -1; - this.remove_style_class_name?.("popup-menu"); - }); - this.connect_named(this, 'destroy', () => { - if (this._drag_monitor !== undefined) { - DND.removeDragMonitor(this._drag_monitor); - this._drag_monitor = undefined; - } - }); - } - - get draggable() { - return this._drag_handle._disabled || false; - } - - set draggable(value) { - this._drag_handle._disabled = value; - this.notify('draggable'); - } - - _on_drag_motion(event) { - if (event.source !== this) return DND.DragMotionResult.CONTINUE; - if (event.targetActor === this._dnd_placeholder) return DND.DragMotionResult.COPY_DROP; - - const panel = find_panel(event.targetActor); - - const previous_sibling = panel?.get_previous_sibling(); - const target_pos = panel?.get_transformed_position(); - const self_size = this.get_transformed_size(); - - this._dnd_placeholder.get_parent()?.remove_child(this._dnd_placeholder); - - if (event.targetActor.is_panel_column) { - event.targetActor.add_child(this._dnd_placeholder); - } else if (panel !== undefined) { - const column = panel.get_parent(); - if (previous_sibling === this._dnd_placeholder || event.y > (target_pos[1] + self_size[1])) { - column.insert_child_above(this._dnd_placeholder, panel); - } else { - column.insert_child_below(this._dnd_placeholder, panel); - } - } - - return DND.DragMotionResult.NO_DROP; - } - }); - GridItem.cache[superclass.name] = klass; - return klass; -}; - -const DropZone = registerClass(class LibPanel_DropZone extends St.Widget { - constructor(source) { - super({ style_class: source._drag_actor?.style_class || source.style_class, opacity: 127 }); - this._delegate = this; - - this._height_constraint = new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.WIDTH, - source: source, - }); - this._width_constraint = new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.HEIGHT, - source: source, - }); - this.add_constraint(this._height_constraint); - this.add_constraint(this._width_constraint); - } - - acceptDrop(source, _actor, _x, _y, _time) { - if (!source.is_grid_item) return false; - - source.get_parent().remove_child(source); - - const column = this.get_parent(); - column.replace_child(this, source); - - column.get_parent()._delegate._cleanup(); - LibPanel.get_instance()._save_layout(); - return true; - } -}); - -class PanelGrid extends PopupMenu { - constructor(sourceActor) { - super(sourceActor, 0, St.Side.TOP); - - // ==== We replace the BoxPointer with our own because we want to make it transparent ==== - global.focus_manager.remove_group(this._boxPointer); - this._boxPointer.bin.set_child(null); // prevent `this.box` from being destroyed - this._boxPointer.destroy(); - // The majority of this code has been copied from here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/popupMenu.js#L801 - - // We want to make the actor transparent - this._boxPointer = new (Semitransparent(BoxPointer))(this._arrowSide); - this.actor = this._boxPointer; - this.actor._delegate = this; - this.actor.style_class = 'popup-menu-boxpointer'; - // Force the popup to take all the screen to allow drag and drop to empty spaces - this.actor.connect_after('parent-set', () => { - if (this._height_constraint) this.actor.remove_constraint(this._height_constraint); - const parent = this.actor.get_parent(); - if (parent === null) { - this._height_constraint = undefined; - } else { - this._height_constraint = new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.HEIGHT, - source: parent, - }); - this.actor.add_constraint(this._height_constraint); - } - }); - // And manually add the bottom margin. This is useless as the grid is invisible, - // but in case something make it visible it looks nice - this.actor.connect_after('stage-views-changed', () => { - if (this.actor.get_stage() === null || this._height_constraint === undefined) return; - this._height_constraint.offset = -this.actor.getArrowHeight(); - }); - - this._boxPointer.bin.set_child(this.box); - this.actor.add_style_class_name('popup-menu'); - this.actor.add_style_class_name('QSAP-panel-grid'); - - global.focus_manager.add_group(this.actor); - this.actor.reactive = true; - // ======================================================================================= - - this.box._delegate = this; // this used so columns can get `this` using `column.get_parent()._delegate` - this.box.vertical = false; - this._panel_style_class = this.box.style_class; // we save the style class that's used to make a nice panel - this.box.style_class = ''; // and we remove it so it's invisible - this.box.style = `spacing: ${GRID_SPACING}px`; - - this.actor.connect_after('notify::allocation', () => { - // The `setTimeout` fixes the following warning: - // Can't update stage views actor ... is on because it needs an allocation. - if (this.actor.x > 0) - this._timeout_id = setTimeout(() => { - this._timeout_id = null; - this._add_column(); - }, 0); - }); - this.actor.connect('destroy', () => { - if (this._timeout_id) clearTimeout(this._timeout_id); - }); - } - - get transparent() { - return this.actor.transparent; - } - - set transparent(value) { - this.actor.transparent = value; - } - - close(animate) { - for (const column of this.box.get_children()) { - column._close(animate); - } - super.close(animate); - } - - _add_panel(panel) { - if (this.box.get_children().length === 0) { - this._add_column()._add_panel(panel); - return; - } - - for (const column of this.box.get_children()) { - if (column._panel_layout.indexOf(panel.panel_name) > -1) { - column._add_panel(panel); - return; - } - } - - // Everything here is really approximated because we can't have the allocations boxes at this point - // Most notably, `max_height` will be wrong - const max_height = this._height_constraint?.source?.height || this.actor.height; - let column; - for (const children of this.box.get_children().reverse()) { - if (this._get_column_height(children) < max_height) { - column = children; - break; - } - } - if (!column) column = this.box.first_child; - if (this._get_column_height(column) > max_height) { - column = this._add_column(); - } - column._add_panel(panel); - } - - _get_column_height(column) { - return column.get_children().reduce((acc, widget) => acc + widget.height, 0); - } - - _add_column(layout = []) { - const column = new PanelColumn(layout); - this.actor.bind_property('transparent', column, 'transparent', GObject.BindingFlags.SYNC_CREATE); - this.box.insert_child_at_index(column, 0); - return column; - } - - _get_panel_layout() { - return this.box.get_children().map(column => column._panel_layout); - } - - _cleanup() { - while (this.box.last_child.get_children().length === 0) this.box.last_child.destroy(); - } - - _get_panels() { - return this.box.get_children().map(column => column.get_children()).flat(); - } -} - -const PanelColumn = registerClass(class LibPanel_PanelColumn extends Semitransparent(St.BoxLayout) { - constructor(layout = []) { - super({ vertical: true, style: `spacing: ${GRID_SPACING}px` }); - this.is_panel_column = true; // since we can't use instanceof, we use this attribute - this._panel_layout = layout; - - this._inhibit_constraint_update = false; - this._width_constraint = new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.WIDTH, - source: null, - }); - this.add_constraint(this._width_constraint); - - this.connect_after_named(this, 'actor-added', (_self, actor) => { - if (this.get_children().length === 1) this.remove_constraint(this._width_constraint); - if (!actor.is_grid_item) return; - - const prev_index = this._panel_layout.indexOf(actor.get_previous_sibling()?.panel_name); - const index = this._panel_layout.indexOf(actor.panel_name); - const next_index = this._panel_layout.indexOf(actor.get_next_sibling()?.panel_name); - // `actor` is in the layout but is misplaced - if (index > -1 && ((prev_index > -1 && index < prev_index) || (next_index > -1 && next_index < index))) { - array_remove(this._panel_layout, actor.panel_name); - index = -1; - } - if (index < 0) { // `actor` is not in the layout - if (prev_index > -1) - array_insert(this._panel_layout, prev_index + 1, actor.panel_name); - else if (next_index > 0) - array_insert(this._panel_layout, next_index - 1, actor.panel_name); - else - array_insert(this._panel_layout, 0, actor.panel_name); - } - }); - this.connect_after_named(this, 'actor-removed', (_self, actor) => { - if (this.get_children().length === 0) this.add_constraint(this._width_constraint); - if (actor._keep_layout || !actor.is_grid_item) return; - - array_remove(this._panel_layout, actor.panel_name); - }); - - this.connect('destroy', () => this._is_destroyed = true); - this.connect_after_named(this, 'parent-set', (_self, old_parent) => { - if (old_parent !== null) this.disconnect_named(old_parent); - - const parent = this.get_parent(); - if (parent === null) return; - const update_source = (_parent, _actor) => { - // clutter is being dumb and emit this signal even though `_parent` and `this` are destroyed - // this fix it - if (this._is_destroyed || this._inhibit_constraint_update) return; - this._width_constraint.source = this.get_next_sibling(); - }; - this.connect_after_named(parent, 'actor-added', update_source); - this.connect_after_named(parent, 'actor-removed', update_source); - - update_source(); - }); - } - - _close(animate) { - for (const panel of this.get_children()) { - panel._close(animate); - } - } - - _add_panel(panel) { - const index = this._panel_layout.indexOf(panel.panel_name); - if (index > -1) { - const panels = this.get_children().map(children => children.panel_name); - for (const panel_name of this._panel_layout.slice(0, index).reverse()) { - const children_index = panels.indexOf(panel_name); - if (children_index > -1) { - this.insert_child_at_index(panel, children_index + 1); - return; - } - } - this.insert_child_at_index(panel, 0); - } else { - this.add_child(panel); - } - } -}); - -export var Panel = registerClass(class LibPanel_Panel extends GridItem(AutoHidable(St.Widget)) { - constructor(panel_name, nColumns = 2) { - super(`${get_extension_uuid()}/${panel_name}`, { - // I have no idea why, but sometimes, a panel (not all of them) gets allocated too much space (behavior similar to `y-expand`) - // This prevent it from taking all available space - y_align: Clutter.ActorAlign.START, - // Enable this so the menu block any click event from propagating through - reactive: true, - // We want to set this later - container: null, - }); - this._delegate = this; - - // Overlay layer that will hold sub-popups - this._overlay = new Clutter.Actor({ layout_manager: new Clutter.BinLayout() }); - - // Placeholder to make empty space when opening a sub-popup - const placeholder = new Clutter.Actor({ - // The placeholder have the same height as the overlay, which means - // it have the same height as the opened sub-popup - constraints: new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.HEIGHT, - source: this._overlay, - }), - }); - - // The grid holding every element - this._grid = new St.Widget({ - style_class: LibPanel.get_instance()._panel_grid._panel_style_class + ' quick-settings quick-settings-grid', - layout_manager: new QuickSettingsLayout(placeholder, { nColumns }), - }); - // Force the grid to take up all the available width. I'm using a constraint because x_expand don't work - this._grid.add_constraint(new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.WIDTH, - source: this, - })); - this.add_child(this._grid); - this.container = this._grid; - this._drag_actor = this._grid; - this._grid.add_child(placeholder); - - this._dimEffect = new Clutter.BrightnessContrastEffect({ enabled: false }); - this._grid.add_effect_with_name('dim', this._dimEffect); - - this._overlay.add_constraint(new Clutter.BindConstraint({ - coordinate: Clutter.BindCoordinate.WIDTH, - source: this._grid, - })); - - this.add_child(this._overlay); - } - - getItems() { - // Every child except the placeholder - return this._grid.get_children().filter(item => item != this._grid.layout_manager._overlay); - } - - getFirstItem() { - return this.getItems[0]; - } - - addItem(item, colSpan = 1) { - this._grid.add_child(item); - this._completeAddItem(item, colSpan); - } - - insertItemBefore(item, sibling, colSpan = 1) { - this._grid.insert_child_below(item, sibling); - this._completeAddItem(item, colSpan); - } - - _completeAddItem(item, colSpan) { - this.setColumnSpan(item, colSpan); - - if (item.menu) { - this._overlay.add_child(item.menu.actor); - - this.connect_named(item.menu, 'open-state-changed', (_, isOpen) => { - this._setDimmed(isOpen); - this._activeMenu = isOpen ? item.menu : null; - // The sub-popup for the power menu is too high. - // I don't know if it's the real source of the issue, but I suspect that the constraint that fixes its y position - // isn't accounting for the padding of the grid, so we add it to the offset manually - // Later: I added the name check because it breaks on the audio panel - // so I'm almost certain that this is not a proper fix - if (isOpen && this.getItems().indexOf(item) == 0 && this.panel_name == "gnome@main") { - const constraint = item.menu.actor.get_constraints()[0]; - constraint.offset = - // the offset is normally bound to the height of the source - constraint.source.height - + this._grid.get_theme_node().get_padding(St.Side.TOP); - // note: we don't reset this property when the item is removed from this panel because - // we hope that it will reset itself (because it's bound to the height of the source), - // which in the case in my tests, but maybe some issue will arise because of this - } - }); - } - if (item._menuButton) { - item._menuButton._libpanel_y_expand_backup = item._menuButton.y_expand; - item._menuButton.y_expand = false; - } - } - - removeItem(item) { - if (!this._grid.get_children().includes(item)) console.error(`[LibPanel] ${get_extension_uuid()} tried to remove an item not in the panel`); - - item.get_parent().remove_child(item); - if (item.menu) { - this.disconnect_named(item.menu); - item.menu.actor.get_parent().remove_child(item.menu.actor); - } - if (item._menuButton) { - item._menuButton.y_expand = item._menuButton._libpanel_y_expand_backup; - item._menuButton._libpanel_y_expand_backup = undefined; - } - } - - getColumnSpan(item) { - if (!this._grid.get_children().includes(item)) console.error(`[LibPanel] ${get_extension_uuid()} tried to get the column span of an item not in the panel`); - - const value = new GObject.Value(); - this._grid.layout_manager.child_get_property(this._grid, item, 'column-span', value); - const column_span = value.get_int(); - value.unset(); - return column_span; - } - - setColumnSpan(item, colSpan) { - if (!this._grid.get_children().includes(item)) console.error(`[LibPanel] ${get_extension_uuid()} tried to set the column span of an item not in the panel`); - - this._grid.layout_manager.child_set_property(this._grid, item, 'column-span', colSpan); - } - - _close(animate) { - this._activeMenu?.close(animate); - } - - _get_ah_children() { - return this.getItems(); - } - - _setDimmed(dim) { - // copied from https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/quickSettings.js - const DIM_BRIGHTNESS = -0.4; - const POPUP_ANIMATION_TIME = 400; - - const val = 127 * (1 + (dim ? 1 : 0) * DIM_BRIGHTNESS); - const color = Clutter.Color.new(val, val, val, 255); - - this._grid.ease_property('@effects.dim.brightness', color, { - mode: Clutter.AnimationMode.LINEAR, - duration: POPUP_ANIMATION_TIME, - onStopped: () => (this._dimEffect.enabled = dim), - }); - this._dimEffect.enabled = true; - } -}); - -// Patching the default to menu to have the exact same api as the one from `Panel`. -// This way, extensions can use them the same way. -QuickSettingsMenu.prototype.getItems = function () { - return this._grid.get_children().filter(item => item != this._grid.layout_manager._overlay); -}; -QuickSettingsMenu.prototype.removeItem = function (item) { - this._grid.remove_child(item); - if (item.menu) { - // it seems that some menus don't have _signalConnectionsByName (probably custom menus) - // we check it exists before using it - if (item.menu._signalConnectionsByName) { - // Manually remove the connection since we don't have its id. - for (const id of item.menu._signalConnectionsByName["open-state-changed"]) { - if (item.menu._signalConnections[id].callback.toString().includes("this._setDimmed")) { - item.menu.disconnect(id); - } - } - } - - this._overlay.remove_child(item.menu.actor); - } -}; -QuickSettingsMenu.prototype.getColumnSpan = function (item) { - const value = new GObject.Value(); - this._grid.layout_manager.child_get_property(this._grid, item, 'column-span', value); - const column_span = value.get_int(); - value.unset(); - return column_span; -}; -QuickSettingsMenu.prototype.setColumnSpan = function (item, colSpan) { - this._grid.layout_manager.child_set_property(this._grid, item, 'column-span', colSpan); -}; - -export class LibPanel { - static _AutoHidable = AutoHidable; - static _Semitransparent = Semitransparent; - static _GridItem = GridItem; - - static _DropZone = DropZone; - static _PanelGrid = PanelGrid; - static _PanelColumn = PanelColumn; - - static get_instance() { - return Main.panel._libpanel; - } - - static get VERSION() { - return LibPanel.get_instance()?.VERSION || VERSION; - } - - // make the main panel available whether it's the gnome one or the libpanel one - static get main_panel() { - return LibPanel.get_instance()?._main_panel || QuickSettings.menu; - } - - static get enabled() { - return LibPanel.enablers.length !== 0; - } - - static get enablers() { - return LibPanel.get_instance()?._enablers || []; - } - - static enable() { - let instance = LibPanel.get_instance(); - if (!instance) { - instance = Main.panel._libpanel = new LibPanel(); - instance._enable(); - }; - if (instance.constructor.VERSION != VERSION) - console.warn(`[LibPanel] ${get_extension_uuid()} depends on libpanel ${VERSION} but libpanel ${instance.constructor.VERSION} is loaded`); - - const uuid = get_extension_uuid(); - if (instance._enablers.indexOf(uuid) < 0) instance._enablers.push(uuid); - } - - static disable() { - const instance = LibPanel.get_instance(); - if (!instance) return; - - const index = instance._enablers.indexOf(get_extension_uuid()); - if (index > -1) instance._enablers.splice(index, 1); - - if (instance._enablers.length === 0) { - instance._disable(); - Main.panel._libpanel = undefined; - }; - } - - static addPanel(panel) { - const instance = LibPanel.get_instance(); - if (!instance) - console.error(`[LibPanel] ${get_extension_uuid()} tried to add a panel, but the library is disabled.`); - - if (instance._settings.get_boolean('padding-enabled')) - set_style(panel._grid, 'padding', `${instance._settings.get_int('padding')}px`); - if (instance._settings.get_boolean('row-spacing-enabled')) - set_style(panel._grid, 'spacing-rows', `${instance._settings.get_int('row-spacing')}px`); - if (instance._settings.get_boolean('column-spacing-enabled')) - set_style(panel._grid, 'spacing-columns', `${instance._settings.get_int('column-spacing')}px`); - instance._panel_grid._add_panel(panel); - instance._save_layout(); - } - - static removePanel(panel) { - panel._keep_layout = true; - panel.get_parent()?.remove_child(panel); - panel._keep_layout = undefined; - } - - constructor() { - this._enablers = []; - - this._patcher = null; - this._settings = null; - this._panel_grid = null; - this._old_menu = null; - } - - _enable() { - const this_path = '/' + split(rsplit(import.meta.url, '/', 1)[0], '/', 3)[3];; - this._settings = get_settings(`${this_path}/org.gnome.shell.extensions.libpanel.gschema.xml`); - - // ======================== Patching ======================== - this._patcher = new Patcher(); - // Permit disabling widget dragging - const _Draggable = DND.makeDraggable(new St.Widget()).constructor; - this._patcher.replace_method(_Draggable, function _grabActor(wrapped, device, touchSequence) { - if (this._disabled) return; - wrapped(device, touchSequence); - }); - // Add named connections to objects - add_named_connections(this._patcher, GObject.Object); - - // =================== Replacing the popup ================== - this._panel_grid = new PanelGrid(QuickSettings); - for (const column of this._settings.get_value("layout").recursiveUnpack().reverse()) { - this._panel_grid._add_column(column); - } - - this._old_menu = this._replace_menu(this._panel_grid); - - const new_menu = new Panel('', 2); - // we do that to prevent the name being this: `quick-settings-audio-panel@rayzeq.github.io/gnome@main` - new_menu.panel_name = 'gnome@main'; - this._move_quick_settings(this._old_menu, new_menu); - LibPanel.addPanel(new_menu); - this._main_panel = new_menu; - - // =================== Compatibility code =================== - //this._panel_grid.box = new_menu.box; // this would override existing properties - //this._panel_grid.actor = = new_menu.actor; - this._panel_grid._dimEffect = new_menu._dimEffect; - this._panel_grid._grid = new_menu._grid; - this._panel_grid._overlay = new_menu._overlay; - this._panel_grid._setDimmed = new_menu._setDimmed.bind(new_menu); - this._panel_grid.getFirstItem = new_menu.getFirstItem.bind(new_menu); - this._panel_grid.addItem = new_menu.addItem.bind(new_menu); - this._panel_grid.insertItemBefore = new_menu.insertItemBefore.bind(new_menu); - this._panel_grid._completeAddItem = new_menu._completeAddItem.bind(new_menu); - - // ================== Visual customization ================== - const set_style_for_panels = (name, value) => { - for (const panel of this._panel_grid._get_panels()) { - set_style(panel._grid, name, value); - } - }; - - this._settings.connect('changed::padding-enabled', () => { - if (this._settings.get_boolean('padding-enabled')) - set_style_for_panels('padding', `${this._settings.get_int('padding')}px`); - else - set_style_for_panels('padding', null); - }); - this._settings.connect('changed::padding', () => { - if (!this._settings.get_boolean('padding-enabled')) return; - set_style_for_panels('padding', `${this._settings.get_int('padding')}px`); - }); - - this._settings.connect('changed::row-spacing-enabled', () => { - if (this._settings.get_boolean('row-spacing-enabled')) - set_style_for_panels('spacing-rows', `${this._settings.get_int('row-spacing')}px`); - else - set_style_for_panels('spacing-rows', null); - }); - this._settings.connect('changed::row-spacing', () => { - if (!this._settings.get_boolean('row-spacing-enabled')) return; - set_style_for_panels('spacing-rows', `${this._settings.get_int('row-spacing')}px`); - }); - - this._settings.connect('changed::column-spacing-enabled', () => { - if (this._settings.get_boolean('column-spacing-enabled')) - set_style_for_panels('spacing-columns', `${this._settings.get_int('column-spacing')}px`); - else - set_style_for_panels('spacing-columns', null); - }); - this._settings.connect('changed::column-spacing', () => { - if (!this._settings.get_boolean('column-spacing-enabled')) return; - set_style_for_panels('spacing-columns', `${this._settings.get_int('column-spacing')}px`); - }); - // https://gjs-docs.gnome.org/gio20~2.0/gio.settings#signal-changed - // "Note that @settings only emits this signal if you have read key at - // least once while a signal handler was already connected for key." - this._settings.get_boolean('padding-enabled'); - this._settings.get_boolean('row-spacing-enabled'); - this._settings.get_boolean('column-spacing-enabled'); - this._settings.get_int('padding'); - this._settings.get_int('row-spacing'); - this._settings.get_int('column-spacing'); - }; - - _disable() { - this._move_quick_settings(this._main_panel, this._old_menu); - this._replace_menu(this._old_menu); - this._old_menu = null; - - this._panel_grid.destroy(); - this._panel_grid = null; - - this._settings = null; - - this._patcher.unpatch_all(); - this._patcher = null; - } - - _replace_menu(new_menu) { - const old_menu = QuickSettings.menu; - - MenuManager.removeMenu(old_menu); - Main.layoutManager.disconnectObject(old_menu); - - QuickSettings.menu = null; // prevent old_menu from being destroyed - QuickSettings.setMenu(new_menu); - old_menu.actor.get_parent().remove_child(old_menu.actor); - - MenuManager.addMenu(new_menu); - Main.layoutManager.connectObject('system-modal-opened', () => new_menu.close(), new_menu); - - return old_menu; - } - - _move_quick_settings(old_menu, new_menu) { - for (const item of old_menu.getItems()) { - const column_span = old_menu.getColumnSpan(item); - const visible = item.visible; - - old_menu.removeItem(item); - - new_menu.addItem(item, column_span); - item.visible = visible; // force reset of visibility - } - } - - _save_layout() { - const layout = this._panel_grid._get_panel_layout(); - - // Remove leading empty columns - while (layout[0]?.length === 0) layout.shift(); - this._settings.set_value( - "layout", - GLib.Variant.new_array( - GLib.VariantType.new('as'), - layout.map(column => GLib.Variant.new_strv(column)) - ) - ); - } -}; diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/patcher.js b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/patcher.js deleted file mode 100644 index e733dee..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/patcher.js +++ /dev/null @@ -1,60 +0,0 @@ -export class Patcher { - constructor() { - this.patchs = {}; - } - - _check_name(name) { - if (name in this.patchs) { - console.error( - `You tried to create a patch named \`${patch_name}\`, but another one already exists with the same name.`, - "This is likely a bug in your extension, so the patch hasn't been applied." - ); - return false; - } - return true; - } - - replace_method(object, new_method, patch_name = undefined) { - const name = new_method.name; - - if (patch_name === undefined) { - patch_name = `${object.name}.${name}`; - if (patch_name in this.patchs) { - console.error( - `It seems you tried to replace the same method twice with this patcher (${object.name}.${name}).`, - "This is likely a bug in your extension, so the patch hasn't been applied.", - "If it's not a bug, you must specify an explicit patch name." - ); - return; - }; - } else if (!this._check_name(patch_name)) return; - - const old_method = object.prototype[new_method.name]; - object.prototype[name] = function () { - return new_method.bind(this)(old_method?.bind(this), ...arguments); - }; - - this.patchs[patch_name] = { type: 'method_replace', object, name, original: old_method }; - } - - unpatch(name) { - const patch = this.patchs[name]; - delete this.patchs[name]; - - switch (patch.type) { - case 'method_replace': { - const { object, name, original } = patch; - object.prototype[name] = original; - break; - } - default: - console.error(`Unknown patch type: ${patch.type}`); - } - } - - unpatch_all() { - for (const name of Object.keys(this.patchs)) { - this.unpatch(name); - } - } -}; \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/utils.js b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/utils.js deleted file mode 100644 index ab08031..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/libpanel/utils.js +++ /dev/null @@ -1,232 +0,0 @@ -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - -const Config = await import("resource:///org/gnome/shell/misc/config.js").catch(async () => - await import("resource:///org/gnome/Shell/Extensions/js/misc/config.js") -); - -export function split(string, sep, maxsplit) { - const splitted = string.split(sep); - return maxsplit ? splitted.slice(0, maxsplit).concat([splitted.slice(maxsplit).join(sep)]) : splitted; -} - -export function rsplit(string, sep, maxsplit) { - const splitted = string.split(sep); - return maxsplit ? [splitted.slice(0, -maxsplit).join(sep)].concat(splitted.slice(-maxsplit)) : splitted; -} - -export function array_remove(array, item) { - const index = array.indexOf(item); - if (index > -1) { - array.splice(index, 1); - return true; - } - return false; -} - -export function array_insert(array, index, ...items) { - array.splice(index, 0, ...items); -} - -export function get_stack() { - return new Error().stack.split('\n').slice(1).map(l => l.trim()).filter(Boolean).map(frame => { - const [func, remaining] = split(frame, '@', 1); - const [file, line, column] = rsplit(remaining, ':', 2); - return { func, file, line, column }; - }); -} - -export function get_extension_uuid() { - const stack = get_stack(); - for (const frame of stack.reverse()) { - if (frame.file.includes('/gnome-shell/extensions/')) { - const [left, right] = frame.file.split('@').slice(-2); - return `${left.split('/').at(-1)}@${right.split('/')[0]}`; - } - } - - return undefined; -} - -export function get_shell_version() { - const [major, minor] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); - return { major, minor }; -} - -export function add_named_connections(patcher, object) { - // this is used to debug things - /*function _get_address(object) { - return object.toString().slice(1, 15); - }*/ - - function set_signal(object, source, signal, callback, id) { - // Add the source map - if (object._lp_connections === undefined) { - object._lp_connections = new Map(); - if (object instanceof GObject.Object) { - object.connect('destroy', () => { - /*console.log(`${object}: removing connections`, - JSON.stringify(object._lp_connections, function simplify(key, value) { - if (value instanceof Map) - return Object.fromEntries(Array.from(value, ([k, v]) => [simplify(null, k), v])); - else if (value instanceof GObject.Object) - return _get_address(value); - else if (value instanceof Function) - return ""; - else - return value; - }) - );*/ - object.disconnect_named(); - }); - } - } - const source_map = object._lp_connections; - - // Add the signal map - if (!source_map.has(source)) { - source_map.set(source, new Map()); - source.connect('destroy', () => { - //console.log(`REMOVING ${_get_address(source)} FROM ${_get_address(object)}`); - source_map.delete(source); - }); - } - const signal_map = source_map.get(source); - - // Add the callback map - if (!signal_map.has(signal)) signal_map.set(signal, new Map()); - const callback_map = signal_map.get(signal); - - //console.log(`CONNECT ${_get_address(source)}::${signal} -> ${_get_address(object)}::${id}`); - //console.log(`Fake connections are ${Object.fromEntries(Object.entries(source?._signalConnections))}`); - - // Add the id - callback_map.set(callback, id); - return id + 100000; // this is just here to prevent any accidental usage of this id with normal disconnect - } - - patcher.replace_method(object, function connect_named(_wrapped, source, signal, callback) { - return set_signal(this, source, signal, callback, source.connect(signal, callback)); - }); - patcher.replace_method(object, function connect_after_named(_wrapped, source, signal, callback) { - return set_signal(this, source, signal, callback, source.connect_after(signal, callback)); - }); - patcher.replace_method(object, function disconnect_named(_wrapped, source = undefined, signal = undefined, callback = undefined) { - if (typeof source === 'number') { - // The function was called with an id. - const id_to_remove = source - 100000; - - const source_map = this._lp_connections; - if (!source_map) return; - for (const [source, signal_map] of source_map.entries()) { - for (const [signal, callback_map] of signal_map.entries()) { - for (const [callback, id] of callback_map.entries()) { - if (id === id_to_remove) { - this.disconnect_named(source, signal, callback); - } - } - } - } - - return; - } - - if (callback !== undefined) { - // Every argments have been provided - const source_map = this._lp_connections; - if (!source_map) return; - const signal_map = source_map.get(source); - if (!signal_map) return; - const callback_map = signal_map.get(signal); - if (!callback_map) return; - const id = callback_map.get(callback); - if (id === undefined) return; - - // console.log(`Disconnecting ${signal} on ${source} with id ${id}`); - // console.log(`Fake connections are ${Object.fromEntries(Object.entries(source?._signalConnections))}`); - if (source.signalHandlerIsConnected?.(id) || (source instanceof GObject.Object && GObject.signal_handler_is_connected(source, id))) - source.disconnect(id); - callback_map.delete(callback); - } else if (signal !== undefined) { - // Only source and signal have been provided - // console.log(`Disconnecting ${signal} on ${source}`); - const source_map = this._lp_connections; - if (!source_map) return; - const signal_map = source_map.get(source); - if (!signal_map) return; - const callback_map = signal_map.get(signal); - if (!callback_map) return; - - for (const callback of callback_map.keys()) { - this.disconnect_named(source, signal, callback); - } - signal_map.delete(signal); - } else if (source !== undefined) { - // Only source have been provided - // console.log(`Disconnecting ${source}`); - const source_map = this._lp_connections; - if (!source_map) return; - const signal_map = source_map.get(source); - if (!signal_map) return; - - for (const signal of signal_map.keys()) { - this.disconnect_named(source, signal); - } - source_map.delete(source); - } else { - // Nothing have been provided - // console.log("Disconnecting everything"); - const source_map = this._lp_connections; - if (!source_map) return; - - for (const source of source_map.keys()) { - this.disconnect_named(source); - } - this._lp_connections.clear(); - } - }); -} - -export function find_panel(widget) { - const panels = []; - - do { - if (widget.is_grid_item) { - panels.push(widget); - } - } while ((widget = widget.get_parent()) !== null); - - return panels.at(-1); -} - -export function get_settings(path) { - const [parent_path, file] = rsplit(path, '/', 1); - const id = rsplit(file, '.', 2)[0]; - const source = Gio.SettingsSchemaSource.new_from_directory( - parent_path, - Gio.SettingsSchemaSource.get_default(), - false - ); - return new Gio.Settings({ settings_schema: source.lookup(id, true) }); -} - -export function get_style(widget) { - return widget.style - ?.split(';') - .map(x => { - const [name, value] = split(x, ':', 1).map(x => x.trim()); - return { name, value }; - }) - .filter(x => x.name !== '') || []; -} - -export function set_style(widget, name, value) { - let style = get_style(widget).filter(x => x.name !== name); - - if (value !== null) - style.push({ name, value }); - - widget.style = style - .map(({ name, value }) => `${name}: ${value}`) - .join(';'); -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/widgets.js b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/widgets.js deleted file mode 100644 index 640fb43..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/libs/widgets.js +++ /dev/null @@ -1,220 +0,0 @@ -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gvc from 'gi://Gvc'; -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Volume from 'resource:///org/gnome/shell/ui/status/volume.js'; - -export function waitProperty(object, name) { - if (!waitProperty.idle_ids) { - waitProperty.idle_ids = []; - } - - return new Promise((resolve, _reject) => { - // very ugly hack - const id_pointer = {}; - const id = GLib.idle_add(GLib.PRIORITY_DEFAULT, waitPropertyLoop.bind(this, resolve, id_pointer)); - id_pointer.id = id; - waitProperty.idle_ids.push(id); - }); - - function waitPropertyLoop(resolve, pointer) { - if (object[name]) { - const index = waitProperty.idle_ids.indexOf(pointer.id); - if (index !== -1) { - waitProperty.idle_ids.splice(index, 1); - } - - resolve(object[name]); - return GLib.SOURCE_REMOVE; - } - return GLib.SOURCE_CONTINUE; - } -} - -// don't know why, but I can't import it directly -const MixerSinkInput = Gvc.MixerSinkInput; -// `_volumeOutput` is set in an async function, so we need to ensure that it's currently defined -const OutputStreamSlider = (await waitProperty(Main.panel.statusArea.quickSettings, '_volumeOutput'))._output.constructor; -const StreamSlider = Object.getPrototypeOf(OutputStreamSlider); - -export class ApplicationsMixer { - constructor(panel, index, filter_mode, filters) { - this.panel = panel; - - // Empty actor used to know where to place sliders - const placeholder = new Clutter.Actor({ visible: false }); - panel._grid.insert_child_at_index(placeholder, index); - - this._sliders = {}; - this._sliders_ordered = [placeholder]; - this._filter_mode = filter_mode; - this._filters = filters.map(f => new RegExp(f)); - - this._mixer_control = Volume.getMixerControl(); - this._sa_event_id = this._mixer_control.connect("stream-added", this._stream_added.bind(this)); - this._sr_event_id = this._mixer_control.connect("stream-removed", this._stream_removed.bind(this)); - - for (const stream of this._mixer_control.get_streams()) { - this._stream_added(this._mixer_control, stream.id); - } - } - - _stream_added(control, id) { - if (id in this._sliders) return; - - const stream = control.lookup_stream_id(id); - if (stream.is_event_stream || !(stream instanceof MixerSinkInput)) { - return; - } - - var matched = false; - for (const filter of this._filters) { - if ((stream.name?.search(filter) > -1) || (stream.description.search(filter) > -1)) { - if (this._filter_mode === 'blacklist') return; - matched = true; - } - } - if (!matched && this._filter_mode === 'whitelist') return; - - const slider = new ApplicationVolumeSlider( - this._mixer_control, - stream, - ); - this._sliders[id] = slider; - - this.panel.addItem(slider, 2); - this.panel._grid.set_child_above_sibling(slider, this._sliders_ordered.at(-1)); - - this._sliders_ordered.push(slider); - } - - _stream_removed(_control, id) { - if (!(id in this._sliders)) return; - - this.panel.removeItem(this._sliders[id]); - this._sliders_ordered.splice(this._sliders_ordered.indexOf(this._sliders[id]), 1); - this._sliders[id].destroy(); - delete this._sliders[id]; - } - - destroy() { - for (const slider of Object.values(this._sliders)) { - this.panel.removeItem(slider); - slider.destroy(); - } - this._sliders = null; - - this._sliders_ordered[0].destroy(); - this._sliders_ordered = null; - - this._mixer_control.disconnect(this._sa_event_id); - this._mixer_control.disconnect(this._sr_event_id); - } -}; - -const ApplicationVolumeSlider = GObject.registerClass(class extends StreamSlider { - constructor(control, stream) { - super(control); - this.menu.setHeader('audio-headphones-symbolic', _('Output Device')); - - try { - GLib.spawn_command_line_sync('pactl'); - } catch (e) { - this._disable_pactl = true; - } - - if (!this._disable_pactl) { - this._control.connectObject( - 'output-added', (_control, id) => this._addDevice(id), - 'output-removed', (_control, id) => this._removeDevice(id), - 'active-output-update', (_control, _id) => this._checkUsedSink(), - this - ); - // unfortunatly we don't have any signal to know that the active device changed - //stream.connect('', () => this._setActiveDevice()); - - for (const sink of control.get_sinks()) { - // apparently it's possible that this function return null - const device = this._control.lookup_device_from_stream(sink)?.get_id(); - if (device) { - this._addDevice(device); - } - } - } - - // This line need to be BEFORE this.stream assignement to prevent an error from appearing in the logs. - this._icons = [stream.name ? stream.name.toLowerCase() : stream.icon_name]; - this.stream = stream; - // And this one need to be after this.stream assignement. - this._icon.fallback_icon_name = stream.icon_name; - - if (!this._disable_pactl) { - this._checkUsedSink(); - } - - this._iconButton.y_expand = false; - this._iconButton.y_align = Clutter.ActorAlign.CENTER; - - const box = this.child; - const sliderBin = box.get_children()[1]; - box.remove_child(sliderBin); - const menu_button_visible = this._menuButton.visible; - box.remove_child(this._menuButton); - - const vbox = new St.BoxLayout({ vertical: true, x_expand: true }); - box.insert_child_at_index(vbox, 1); - - const hbox = new St.BoxLayout(); - hbox.add_child(sliderBin); - hbox.add_child(this._menuButton); - this._menuButton.visible = menu_button_visible; // we need to reset `actor.visible` when changing parent - // this prevent the tall panel bug when the button is shown - this._menuButton.y_expand = false; - - const label = new St.Label({ natural_width: 0 }); - label.style_class = "QSAP-application-volume-slider-label"; - stream.bind_property_full('description', label, 'text', - GObject.BindingFlags.SYNC_CREATE, - (_binding, _value) => { - return [true, this._get_label_text(stream)]; - }, - null - ); - - vbox.add_child(label); - vbox.add_child(hbox); - } - - _get_label_text(stream) { - const { name, description } = stream; - return name === null ? description : `${name} - ${description}`; - } - - _checkUsedSink() { - let [, stdout, ,] = GLib.spawn_command_line_sync('pactl -f json list sink-inputs'); - if (stdout instanceof Uint8Array) - stdout = new TextDecoder().decode(stdout); - stdout = JSON.parse(stdout); - - for (const sink_input of stdout) { - if (sink_input.index === this.stream.index) { - const sink_id = this._control.lookup_device_from_stream(this._control.get_sinks().find(s => s.index === sink_input.sink))?.get_id(); - if (sink_id) { - this._setActiveDevice(sink_id); - } - } - } - } - - _lookupDevice(id) { - return this._control.lookup_output_id(id); - } - - _activateDevice(device) { - GLib.spawn_command_line_async(`pactl move-sink-input ${this.stream.index} ${this._control.lookup_stream_id(device.stream_id).index}`); - this._setActiveDevice(device.get_id()); - } -}); diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/cs/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/cs/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo deleted file mode 100644 index 6900b8121fce2d7c04ba9aed5242e4ac1f6d8768..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 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 P{h0Dp?lld+Z2;=Oj)M~H diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/nl/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/locale/nl/LC_MESSAGES/quick-settings-audio-panel@rayzeq.github.io.mo deleted file mode 100644 index 5d0222a969b59972435eaaac8f202b04668df7a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3597 zcmaKu+ixUC6~-$eAz&^G3HNI)EXu~&@%oa4$cxFY<6Z2q#%9;BfDou>x@M+5HC3&y zYLC4F2?+@)JOB!Ue*pf7D2P1sfOv{{iNq@)p$LS;3oramb z;BUeAgTHU_kKlW_e-nHJ{A>ICAK(|b|1T)}F7omMxDGx6z65>({2n*~Pe8HzuNKv# zO6_oe0pw48o3H1zEKy6~7%Pl8W?*THL`#PZ-SDSyWnTQ68t6j^Y;DcF)DVS;cFYb4oW^=1~2J^@qG>dm%*pGe+AqGUkBNu9)ct?%r5ArJR(cdL3~axiA%RP9|Awi zN3?nH`UnriHld_kOa3KRsjpA-kvfo?5`9GrxkLle?}L0KZ_rEE#TG?NxgO>t`b+Jk z>xQ*{qECFSqu2eyMpNlHG&;n}WaGg9S=3?3n!415OYgF>v_&tAg?D;f9J6C_u?~eB z=*kStu?dTd>V}z-=`!DbAV2#(~H(&d`8B)b88Gw3`HJl*Fgn^>}-LV0t#rf{1-ak)ZaR z?oK60e6Qd$_J%^=OykNbgVbXz=el3{abhc?Eot^ohD9`T*Y5Yuo}6Q3Qdq0IntP0LbcHDa4%ZW60RK5H}+`o1*IMDhQtyV|>y?{o*)9qPz6~Cvn(nJ?*L)ZFMm8!2~T?POUhLdN_+30yNC|Z55^l znl3wKD5LeH)q9zP4kk!rnH|+_?b9z)GQrop4kku8W6+oCUONeDo9l_uxo?6Xx>Mbw zUtpaiQ;5$Zk{Xk36oT~(4g{%;Wq{BcbgrzOi;RJ`e${^E4^1z2cJj_QO%zFMc0$dJ=_qwn{P4f;zMiCG;&xZYk6L=^QW_*Y#FS zTh1P?YiAdBcXn^inXW7?FTBW9p^iESCnb!cIgVFLOJQ8oyb0e{rIiJ>U6^WYj2_jLcCCko0{8Sqkl`IrVIXBr<2U0ARmLponqh5AeMHeL zE;8Y3iy5QqBIZ>+8nM+lCVrZTeeYc}(MHafI(Q&W@O%#PGfG-D_XWMZ|mpSfQ%T1!2wi@adE zm)49l`DZ`5#^3G2jb!vw%U!;VBP#W^xmD?l4W*|@3s~x9vqwgoFl2R!mJ&_olrd>FxVXZk4Dr4NpOGWel1ocgo zr`%y6ZDl+qYm6W{CXoG%u?%t9eA*H_+oOjU0~5({zC_|=MDmU!qa$a=ChDj5E{xiy zT{*NyEjLPmg{QKlFH=4P!x{#<GAOm7%v0P$OcWo)R6eyT0+N7Pr) zoCmChap@?Jc|Gf_7Yox*$2@5djC9V9&ebF}k(;x%s{LaR zz^C$|zWfB_91=0Z|1m_m&m1-EgUY}p;}XosaQITRIFz{*PUv$p=2swsNr&F!2pxOg zq { - const new_row = new Adw.EntryRow({ 'title': _("Stream name") }); - if (text != undefined) new_row.text = text; - - const delete_button = new Gtk.Button({ icon_name: 'user-trash-symbolic', has_frame: false }); - delete_button.connect('clicked', () => { - mixer_filter_group.remove(new_row); - filters.splice(filters.indexOf(new_row), 1); - save_filters(settings, filters); - }); - new_row.add_suffix(delete_button); - - new_row.connect('changed', () => save_filters(settings, filters)); - - filters.push(new_row); - mixer_filter_group.add(new_row); - }; - add_filter_button.connect('clicked', () => { - create_filter_row(); - }); - - for (const filter of settings.get_strv('filters')) { - create_filter_row(filter); - } - - // ==================================== LibPanel group ==================================== - // we remove the 'file://' and the filename at the end - const parent_folder = '/' + split(rsplit(get_stack()[0].file, '/', 1)[0], '/', 3)[3]; - const libpanel_settings = get_settings(`${parent_folder}/libs/libpanel/org.gnome.shell.extensions.libpanel.gschema.xml`); - const libpanel_group = new Adw.PreferencesGroup({ - title: _("LibPanel settings"), - description: _("Those settings are not specific to this extension, they apply to every panels"), - }); - page.add(libpanel_group); - - libpanel_group.add(create_switch_spin( - libpanel_settings, 'padding-enabled', 'padding', - { - title: _("Padding"), - subtitle: _("Use this to override the default padding of the panels") - }, 0, 100 - )); - libpanel_group.add(create_switch_spin( - libpanel_settings, 'row-spacing-enabled', 'row-spacing', - { - title: _("Row spacing"), - subtitle: _("Use this to override the default row spacing of the panels") - }, 0, 100 - )); - libpanel_group.add(create_switch_spin( - libpanel_settings, 'column-spacing-enabled', 'column-spacing', - { - title: _("Column spacing"), - subtitle: _("Use this to override the default column spacing of the panels") - }, 0, 100 - )); - } -} - - -function create_switch(settings, id, options) { - const row = new Adw.SwitchRow(options); - settings.bind( - id, - row, - 'active', - Gio.SettingsBindFlags.DEFAULT - ); - return row; -} - -function create_dropdown(settings, id, options) { - const fields = options.fields; - delete options.fields; - - const model = Gtk.StringList.new(fields.map(x => x[1])); - const row = new Adw.ComboRow({ - model: model, - selected: fields.map(x => x[0]).indexOf(settings.get_string(id)), - ...options - }); - - row.connect('notify::selected', () => { - settings.set_string(id, fields[row.selected][0]); - }); - - return row; -} - -function create_switch_spin(settings, switch_id, spin_id, options, lower = 0, higher = 100) { - const row = Adw.SpinRow.new_with_range(lower, higher, 1); - row.title = options.title; - row.subtitle = options.subtitle; - - const switch_ = new Gtk.Switch({ valign: Gtk.Align.CENTER }); - settings.bind( - switch_id, - switch_, - 'active', - Gio.SettingsBindFlags.DEFAULT - ); - row.add_prefix(switch_); - row.activatable_widget = switch_; - - settings.bind( - spin_id, - row, - 'value', - Gio.SettingsBindFlags.DEFAULT - ); - - return row; -} - -function save_filters(settings, filters) { - settings.set_strv('filters', filters.map(filter => filter.text)); -} - -// From this point onwards, the code is mostly a reimplementation of this: -// https://gitlab.gnome.org/GNOME/gnome-control-center/-/tree/main/panels/search - -const ReorderablePreferencesGroup = GObject.registerClass(class extends Adw.PreferencesGroup { - constructor(settings, key, options) { - super(options); - this._settings = settings; - this._key = key; - - this._list_box = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE }); - this._list_box.add_css_class('boxed-list'); - this._list_box.set_sort_func((a, b) => { - const data = settings.get_strv(key); - const index_a = data.indexOf(a.id); - const index_b = data.indexOf(b.id); - return index_a < index_b ? -1 : 1; - }); - super.add(this._list_box); - } - - add(row) { - this._list_box.set_valign(Gtk.Align.FILL); - row.connect('move-row', (source, target) => { - this.selected_row = source; - const data = this._settings.get_strv(this._key); - const source_index = data.indexOf(source.id); - const target_index = data.indexOf(target.id); - if (target_index < source_index) { - data.splice(source_index, 1); // remove 1 element at source_index - data.splice(target_index, 0, source.id); // insert source.id at target_index - } else { - data.splice(target_index + 1, 0, source.id); // insert source.id at target_index - data.splice(source_index, 1); // remove 1 element at source_index - } - this._settings.set_strv(this._key, data); - this._list_box.invalidate_sort(); - }); - this._list_box.append(row); - } -}); - -class DraggableRowClass extends Adw.ActionRow { - constructor(id, options) { - super(options); - - this.id = id; - - const drag_handle = new Gtk.Image({ icon_name: 'list-drag-handle-symbolic' }); - // css don't work - drag_handle.add_css_class('drag-handle'); - this.add_prefix(drag_handle); - - const drag_source = new Gtk.DragSource({ actions: Gdk.DragAction.MOVE }); - drag_source.connect('prepare', (source, x, y) => { - this._drag_x = x; - this._drag_y = y; - return Gdk.ContentProvider.new_for_value(this); - }); - drag_source.connect('drag-begin', (source, drag) => { - this._drag_widget = new Gtk.ListBox(); - this._drag_widget.set_size_request(this.get_allocated_width(), this.get_allocated_height()); - - const row_copy = new DraggableRow("", options); - this._drag_widget.append(row_copy); - this._drag_widget.drag_highlight_row(row_copy); - - Gtk.DragIcon.get_for_drag(drag).set_child(this._drag_widget); - drag.set_hotspot(this._drag_x, this._drag_y); - }); - this.add_controller(drag_source); - - const drop_target = Gtk.DropTarget.new(DraggableRow, Gdk.DragAction.MOVE); - drop_target.preload = true; - drop_target.connect('drop', (target, source, x, y) => { - source.emit('move-row', this); - - return true; - }); - this.add_controller(drop_target); - } -} - -const DraggableRow = GObject.registerClass({ - Signals: { - flags: GObject.SignalFlags.RUN_LAST, - 'move-row': { - param_types: [DraggableRowClass], - } - }, -}, DraggableRowClass); diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/gschemas.compiled deleted file mode 100644 index bb1bf5c89f20c950e3fa6334686bac6d0b532f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 964 zcmZ`&F>4e-6rQN(B{@tXMgoE$2<|Dfi-l;J!l0mS#3ta}?sz+7c4pm~y-S27Hg*=l zU*Hc&6ST51pp9VVFGyo6)}o%@o4w81IPmTF?KiXU-n{qj-Xl>dVLY3z74YLmN2jLV z9Qgggh9joETkJmD2Y-RlS!Qg4b#xjAd&r1C0k#^(Lt_gWyIg7=%PlXBQ`WfnS*_Ad z?xgq13>_DBrYtXok(xp<7WEnqPYTBRkw#Y6g`~3~zR+W_?YPVBm@8A(e){WlfPNoOq!$)i z5c+l&ya1pyp@-DtFax}_PI(Lp46K3m-WLDl>TL2sD~pp!7rNf_v4Hqgoc2RdQQHN|%!3LcSg s{X$kl*^WHwV=J@@e+FzfmF2efC}aB;YRU?_7z^EHOP8)(3!y0NUzbAV3jhEB diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/org.gnome.shell.extensions.quick-settings-audio-panel.gschema.xml b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/org.gnome.shell.extensions.quick-settings-audio-panel.gschema.xml deleted file mode 100644 index fd27e05..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/schemas/org.gnome.shell.extensions.quick-settings-audio-panel.gschema.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - true - - - false - - - - - - - - "move" - - - true - - - false - - - - - - - "bottom" - - - - ["volume-output", "volume-input", "media", "mixer"] - - - - - - - - "blacklist" - - - [] - - - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/stylesheet.css b/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/stylesheet.css deleted file mode 100644 index a807950..0000000 --- a/.local/share/gnome-shell/extensions/quick-settings-audio-panel@rayzeq.github.io/stylesheet.css +++ /dev/null @@ -1,62 +0,0 @@ -.QSAP-panel-grid { - box-shadow: none; -} - -.QSAP-panel-separated { - /* Add spacing between panels */ - margin-bottom: 5px; - margin-left: 5px; - /* There is too much blank space in the top and bottom of the new panel, we reduce it */ - padding-top: 10px; - padding-bottom: 10px; -} - -.QSAP-panel-merged { - /* There is too much blank space in the bottom of the new panel, we remove it. - * Unfortunatly, negative margins are not supported so we can't */ - /*margin-bottom: -10px;*/ -} - -.QSAP-media-section { - /* Add margins because it's too close to sliders */ - margin-top: 5px; - margin-bottom: 8px; -} - -.QSAP-media-section .message { - /* Limit width to 100 px */ - width: 100px; - /* Make margins smaller */ - margin: 2px 0px 0px 0px; - /* Smoother corners */ - border-radius: 22px; - /* Allow for a more compact layout */ - margin: 0px; -} - -.QSAP-media-section .message-icon-bin { - /* Compact layout */ - padding: 12px; - padding-left: 15px; - padding-right: 0px; -} - -.QSAP-media-section .media-message-cover-icon.fallback { - /* Make the fallback icon (the note) the same size as other icons */ - padding: 9px; -} - -.QSAP-media-section .message-media-control { - /* Move control buttons closer to each other */ - padding-left: 5px; - padding-right: 5px; -} - -.QSAP-application-volume-slider-label { - /* Align text with bar */ - padding-left: 6px; - /* Make the text smaller */ - font-size: 0.92em; - /* Nice ellepsis if the text overflow */ - text-overflow: ellipsis; -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/extension.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/extension.js deleted file mode 100644 index 353848c..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/extension.js +++ /dev/null @@ -1,362 +0,0 @@ -/* 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 - * 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 - */ - -import { Gio, GLib, Meta } from './src/dependencies/gi.js'; -import { Extension, Main } from './src/dependencies/shell.js'; - -import MoveHandler from './src/extension/moveHandler.js'; -import ResizeHandler from './src/extension/resizeHandler.js'; -import KeybindingHandler from './src/extension/keybindingHandler.js'; -import LayoutsManager from './src/extension/layoutsManager.js'; -import ActiveWindowHint from './src/extension/activeWindowHint.js'; -import AltTabOverride from './src/extension/altTab.js'; -import { Rect } from './src/extension/utility.js'; - -/** - * 2 entry points: - * 1. keyboard shortcuts: - * => keybindingHandler.js - * 2. Grabbing a window: - * => moveHandler.js (when moving a window) - * => resizeHandler.js (when resizing a window) - */ - -class SettingsOverrider { - constructor(settingsSingleton) { - this._settings = settingsSingleton; - this._overrides = new Map(); - this._originalSettings = new Map(); - this._maybeNullValue = GLib.Variant.new_maybe( - new GLib.VariantType('b'), null); - - const savedSettings = this._settings.getUserValue('overridden-settings'); - this._wasOverridden = savedSettings !== null; - } - - _maybeUpdateOverriden(schemaId, key, value) { - if (this._wasOverridden) - return undefined; - - const savedSettings = this._settings.getValue( - 'overridden-settings').deepUnpack(); - const prefKey = `${schemaId}.${key}`; - const oldValue = savedSettings[prefKey]; - - if (value !== undefined) - savedSettings[prefKey] = value ?? this._maybeNullValue; - else - delete savedSettings[prefKey]; - - this._settings.setValue('overridden-settings', - new GLib.Variant('a{sv}', savedSettings)); - - return oldValue; - } - - add(settings, key, value) { - this._originalSettings.set(settings.schemaId, settings); - const userValue = settings.get_user_value(key); - - const values = this._overrides.get(settings.schemaId) ?? new Map(); - if (!values.size) - this._overrides.set(settings.schemaId, values); - values.set(key, userValue); - - settings.set_value(key, value); - - this._maybeUpdateOverriden(settings.schemaId, key, - userValue ?? this._maybeNullValue); - } - - remove(schema, key) { - const settings = this._originalSettings.get(schema); - if (!settings) - return; - - const values = this._overrides.get(settings.schemaId); - const value = values?.get(key); - - if (value === undefined) - return; - - if (value) - settings.set_value(key, value); - else - settings.reset(key); - - values.delete(key); - this._maybeUpdateOverriden(settings.schemaId, key, undefined); - } - - _clear() { - if (this._wasOverridden) { - const savedSettings = this._settings.getValue( - 'overridden-settings').unpack(); - - Object.entries(savedSettings).forEach(([path, value]) => { - const splits = path.split('.'); - const key = splits.at(-1); - const schemaId = splits.slice(0, -1).join('.'); - - const settings = this._originalSettings.get(schemaId) ?? - new Gio.Settings({ schema_id: schemaId }); - - value = value.get_variant(); - if (value.equal(this._maybeNullValue)) - settings.reset(key); - else - settings.set_value(key, value); - }); - } else { - this._originalSettings.forEach(settings => { - this._overrides.get(settings.schemaId).forEach((value, key) => { - if (value) - settings.set_value(key, value); - else - settings.reset(key); - }); - }); - } - - this._settings.reset('overridden-settings'); - } - - destroy() { - this._clear(); - this._maybeNullValue = null; - this._originalSettings = null; - this._overrides = null; - this._settings = null; - } -} - -export default class TilingAssistantExtension extends Extension { - async enable() { - this.settings = (await import('./src/common.js')).Settings; - this.settings.initialize(this.getSettings()); - this._settingsOverrider = new SettingsOverrider(this.settings); - - const twmModule = await import('./src/extension/tilingWindowManager.js'); - - this._twm = twmModule.TilingWindowManager; - this._twm.initialize(); - - this._moveHandler = new MoveHandler(); - this._resizeHandler = new ResizeHandler(); - this._keybindingHandler = new KeybindingHandler(); - this._layoutsManager = new LayoutsManager(); - this._activeWindowHintHandler = new ActiveWindowHint(); - this._altTabOverride = new AltTabOverride(); - - // Disable native tiling. - this._settingsOverrider.add(new Gio.Settings({ - schema_id: 'org.gnome.mutter' - }), 'edge-tiling', new GLib.Variant('b', false)); - - // Disable native keybindings for Super+Up/Down/Left/Right - const gnomeMutterKeybindings = new Gio.Settings({ - schema_id: 'org.gnome.mutter.keybindings' - }); - const gnomeDesktopKeybindings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.wm.keybindings' - }); - const sc = (await import('./src/common.js')).Shortcuts; - const emptyStrvVariant = new GLib.Variant('as', []); - - if (gnomeDesktopKeybindings.get_strv('maximize').includes('Up') && - this.settings.getStrv(sc.MAXIMIZE).includes('Up')) { - this._settingsOverrider.add(gnomeDesktopKeybindings, - 'maximize', emptyStrvVariant); - } - if (gnomeDesktopKeybindings.get_strv('unmaximize').includes('Down') && - this.settings.getStrv(sc.RESTORE_WINDOW).includes('Down')) { - this._settingsOverrider.add(gnomeDesktopKeybindings, - 'unmaximize', emptyStrvVariant); - } - if (gnomeMutterKeybindings.get_strv('toggle-tiled-left').includes('Left') && - this.settings.getStrv(sc.LEFT).includes('Left')) { - this._settingsOverrider.add(gnomeMutterKeybindings, - 'toggle-tiled-left', emptyStrvVariant); - } - if (gnomeMutterKeybindings.get_strv('toggle-tiled-right').includes('Right') && - this.settings.getStrv(sc.RIGHT).includes('Right')) { - this._settingsOverrider.add(gnomeMutterKeybindings, - 'toggle-tiled-right', emptyStrvVariant); - } - - // Include tiled windows when dragging from the top panel. - this._getDraggableWindowForPosition = Main.panel._getDraggableWindowForPosition; - Main.panel._getDraggableWindowForPosition = function (stageX) { - const workspaceManager = global.workspace_manager; - const windows = workspaceManager.get_active_workspace().list_windows(); - const allWindowsByStacking = global.display.sort_windows_by_stacking(windows).reverse(); - - return allWindowsByStacking.find(w => { - const rect = w.get_frame_rect(); - const workArea = w.get_work_area_current_monitor(); - return w.is_on_primary_monitor() && - w.showing_on_its_workspace() && - w.get_window_type() !== Meta.WindowType.DESKTOP && - (w.maximized_vertically || w.tiledRect?.y === workArea.y) && - stageX > rect.x && stageX < rect.x + rect.width; - }); - }; - - // Restore tiled window properties after session was unlocked. - this._loadAfterSessionLock(); - - // Setting used for detection of a fresh install and do compatibility - // changes if necessary... - this.settings.setInt('last-version-installed', this.metadata.version); - } - - disable() { - // Save tiled window properties, if the session was locked to restore - // them after the session is unlocked again. - this._saveBeforeSessionLock(); - - this._settingsOverrider.destroy(); - this._settingsOverrider = null; - this._moveHandler.destroy(); - this._moveHandler = null; - this._resizeHandler.destroy(); - this._resizeHandler = null; - this._keybindingHandler.destroy(); - this._keybindingHandler = null; - this._layoutsManager.destroy(); - this._layoutsManager = null; - this._activeWindowHintHandler.destroy(); - this._activeWindowHintHandler = null; - - this._altTabOverride.destroy(); - this._altTabOverride = null; - - this._twm.destroy(); - this._twm = null; - - this.settings.destroy(); - this.settings = null; - - // Restore old functions. - Main.panel._getDraggableWindowForPosition = this._getDraggableWindowForPosition; - this._getDraggableWindowForPosition = null; - - // Delete custom tiling properties. - const openWindows = global.display.get_tab_list(Meta.TabList.NORMAL, null); - openWindows.forEach(w => { - delete w.isTiled; - delete w.tiledRect; - delete w.untiledRect; - }); - } - - /** - * Extensions are disabled when the screen is locked. So save the custom tiling - * properties of windows before locking the screen. - */ - _saveBeforeSessionLock() { - if (!Main.sessionMode.isLocked) - return; - - this._wasLocked = true; - - const rectToJsObj = rect => rect && { - x: rect.x, - y: rect.y, - width: rect.width, - height: rect.height - }; - - // can't just check for isTiled because maximized windows may - // have an untiledRect as well in case window gaps are used - const openWindows = this._twm.getWindows(true); - const savedWindows = openWindows.filter(w => w.untiledRect).map(w => { - return { - windowId: w.get_stable_sequence(), - isTiled: w.isTiled, - tiledRect: rectToJsObj(w.tiledRect), - untiledRect: rectToJsObj(w.untiledRect) - }; - }); - - const saveObj = { - 'windows': savedWindows, - 'tileGroups': Array.from(this._twm.getTileGroups()) - }; - - const userPath = GLib.get_user_config_dir(); - const parentPath = GLib.build_filenamev([userPath, '/tiling-assistant']); - const parent = Gio.File.new_for_path(parentPath); - try { parent.make_directory_with_parents(null); } catch (e) {} - const path = GLib.build_filenamev([parentPath, '/tiledSessionRestore.json']); - const file = Gio.File.new_for_path(path); - try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} - file.replace_contents(JSON.stringify(saveObj), null, false, - Gio.FileCreateFlags.REPLACE_DESTINATION, null); - } - - /** - * Extensions are disabled when the screen is locked. After having saved them, - * reload them here. - */ - _loadAfterSessionLock() { - if (!this._wasLocked) - return; - - this._wasLocked = false; - - const userPath = GLib.get_user_config_dir(); - const path = GLib.build_filenamev([userPath, '/tiling-assistant/tiledSessionRestore.json']); - const file = Gio.File.new_for_path(path); - if (!file.query_exists(null)) - return; - - try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} - const [success, contents] = file.load_contents(null); - if (!success || !contents.length) - return; - - const openWindows = this._twm.getWindows(true); - const saveObj = JSON.parse(new TextDecoder().decode(contents)); - - const windowObjects = saveObj['windows']; - windowObjects.forEach(wObj => { - const { windowId, isTiled, tiledRect, untiledRect } = wObj; - const window = openWindows.find(w => w.get_stable_sequence() === windowId); - if (!window) - return; - - const jsToRect = jsRect => jsRect && new Rect( - jsRect.x, jsRect.y, jsRect.width, jsRect.height - ); - - window.isTiled = isTiled; - window.tiledRect = jsToRect(tiledRect); - window.untiledRect = jsToRect(untiledRect); - }); - - const tileGroups = new Map(saveObj['tileGroups']); - this._twm.setTileGroups(tileGroups); - openWindows.forEach(w => { - if (tileGroups.has(w.get_id())) { - const group = this._twm.getTileGroupFor(w); - this._twm.updateTileGroup(group); - } - }); - } -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/cs/LC_MESSAGES/tiling-assistant@leleat-on-github.mo b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/cs/LC_MESSAGES/tiling-assistant@leleat-on-github.mo deleted file mode 100644 index 9247b9f2ec354ea196b52344f1ffd8da6486136a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1601 zcmZ{jO>7%Q6vqcz3YhQmsj5g%6-onW&D!Z9a^il_rd4RIxQPiMabUbVT~BsBv)Uam zjn8o4P>BN|Ax@P*s0Rc$B!r5PlQW-p9y!pT9nLmym z{#3x8!8nfbBgTsu@7{+W*stKj;BVlA;P2o=;9al+{tdna{tG?=9=~6R=fGL;Dew&V zICvF&8hj7rvmE#+_!0OR_!-FizXYEIzXN&y&mhO$0iOl`1Ub(?;D@Z?(D=NM50CYI z4L*VOZ$Xax39N&6cIHPO5aI>QkAbXn4rG0AfUN5skk2t7=lK9+J)eNA=PU4e@OzN+ z`~n^W{{m;gLr2DWUjZSnG~Um~ePrW$IXCx@d&&lR<@x-56a!_Ib@Q1>T^drB#{Eb6 zWxu$_UE?~$xq-7@M<+^LQbuJm5tlOAr6m)NKh~VgoLDx6%5p^=o6=g4DP?FWj1-*< zoVJEKy00>ES#5T;3AKrGv8r-sGevK~Vc(}UJyc|k;DfMJI|Nb7hHC6_mb%tC+dnY% z5_QcT^kq8gO`ZE9_Afb`PWIw^e=>GV!dXq*rUS&=D1yY35IS+5-1WBPb=}uP$u*01 zW;ayeyyehaM{nS2P-Ru6HgjGpk96q0K8SL!W8rSEc&n<=9OPY)PBp0R*K3|X@A-4& z*BXBPRln~0l`ArLUMG_#PbAvcpmn?9w!R2@)K-}peG}87+gU}b{A{YS!fsT9;c09& z(LhGZ>nPc8(D|XluEogMzVd?HOLXqemb0qOqG@=8g1pjNZY@oVs8#*Sd25_9(6X6A ztW($BYiT02S)iaNaS>ee&CW${ej3NBuBpshGJ)kA(4hIQc9nKAz?JeY+N_^9$fV^o zZ_X{y__H}{n$6nFbcTFt(5yM#tkcX4nZ@QQcGlpmFI3+4#&@%9N!u#iAF5YRRp%<@ z_3h&i3F6T$3KO|~JJf*^D_s?s(Jc{M6KEO)J)0`@PYmVOjnPdP5BB)VyFJ7zZQYQ$ zEf7L74ixn)_q=Dx#+lr}{q1IQXp4ALTuw$e3x!x5I>e%bZ>4K&0bzwobZm2nT}G0T zcnaIMb)QB*q?s%x8pVZOu@qXozWq}w5>?oHoSb2=_h3|UFu=&3-Tr)U_8reX2Tc6q p6ziLLEMqhyKwnUaoeFOwVQTEa(TV?$Iw7WEeSS7F!NUo(_z(Z(zBm8? diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/de_CH/LC_MESSAGES/tiling-assistant@leleat-on-github.mo b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/locale/de_CH/LC_MESSAGES/tiling-assistant@leleat-on-github.mo deleted file mode 100644 index 432fe7eecbdb81a8f8ade05bb2fef506e26e6fba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8980 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ɔyFm~Z>;4g#sftY;odGIj!HBjfh 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 Os=F|kc3!-~Fv@Q<@O;bw diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/insert-link-symbolic.svg b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/insert-link-symbolic.svg deleted file mode 100644 index 9ebba0e..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/insert-link-symbolic.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/preferences-desktop-apps-symbolic.svg b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/preferences-desktop-apps-symbolic.svg deleted file mode 100644 index 7188428..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/media/preferences-desktop-apps-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/metadata.json b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/metadata.json deleted file mode 100644 index e924656..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Expand GNOME's 2 column tiling and add a Windows-snap-assist-inspired popup...", - "gettext-domain": "tiling-assistant@leleat-on-github", - "name": "Tiling Assistant", - "settings-schema": "org.gnome.shell.extensions.tiling-assistant", - "shell-version": [ - "45" - ], - "url": "https://github.com/Leleat/Tiling-Assistant", - "uuid": "tiling-assistant@leleat-on-github", - "version": 44 -} \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/prefs.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/prefs.js deleted file mode 100644 index 8f92c61..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/prefs.js +++ /dev/null @@ -1,304 +0,0 @@ -import { Gdk, Gio, GLib, Gtk } from './src/dependencies/prefs/gi.js'; -import { ExtensionPreferences } from './src/dependencies/prefs.js'; - -import LayoutPrefs from './src/prefs/layoutsPrefs.js'; -import { Settings, Shortcuts } from './src/common.js'; -// eslint-disable-next-line no-unused-vars -import { ShortcutListener } from './src/prefs/shortcutListener.js'; - -export default class Prefs extends ExtensionPreferences { - fillPreferencesWindow(window) { - // Load css file - const provider = new Gtk.CssProvider(); - const path = GLib.build_filenamev([this.path, 'stylesheet.css']); - provider.load_from_path(path); - Gtk.StyleContext.add_provider_for_display( - Gdk.Display.get_default(), - provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - window.set_can_navigate_back(true); - - const settings = this.getSettings(); - const builder = new Gtk.Builder(); - builder.set_translation_domain(this.uuid); - builder.add_from_file(`${this.path}/src/ui/prefs.ui`); - - // Add general preference page - window.add(builder.get_object('general')); - - // Add keybindings preference page - window.add(builder.get_object('keybindings')); - - // Add layouts preference page on condition of advanced setting - const layoutsPage = builder.get_object('layouts'); - settings.connect(`changed::${Settings.ENABLE_ADV_EXP_SETTINGS}`, () => { - settings.get_boolean(Settings.ENABLE_ADV_EXP_SETTINGS) - ? window.add(layoutsPage) - : window.remove(layoutsPage); - }); - - if (settings.get_boolean(Settings.ENABLE_ADV_EXP_SETTINGS)) - window.add(layoutsPage); - - // Bind settings to GUI - this._bindSwitches(settings, builder); - this._bindSpinbuttons(settings, builder); - this._bindComboRows(settings, builder); - this._bindRadioButtons(settings, builder); - this._bindKeybindings(settings, builder); - this._bindColorButtons(settings, builder); - - // LayoutPrefs manages everything related to layouts on the - // prefs side (including the keyboard shortcuts) - new LayoutPrefs(settings, builder, this.path); - - // Set visibility for deprecated settings - this._setDeprecatedSettings(settings, builder); - - // Add a button into the headerbar with info - this._addHeaderBarInfoButton(window, settings, builder); - } - - /* - * Bind GUI switches to settings. - */ - _bindSwitches(settings, builder) { - const switches = [ - Settings.ENABLE_TILING_POPUP, - Settings.POPUP_ALL_WORKSPACES, - Settings.RAISE_TILE_GROUPS, - Settings.TILEGROUPS_IN_APP_SWITCHER, - Settings.MAXIMIZE_WITH_GAPS, - Settings.SHOW_LAYOUT_INDICATOR, - Settings.ENABLE_ADV_EXP_SETTINGS, - Settings.DISABLE_TILE_GROUPS, - Settings.LOW_PERFORMANCE_MOVE_MODE, - Settings.MONITOR_SWITCH_GRACE_PERIOD, - Settings.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT, - Settings.ENABLE_TILE_ANIMATIONS, - Settings.ENABLE_UNTILE_ANIMATIONS, - Settings.ENABLE_HOLD_INVERSE_LANDSCAPE, - Settings.ENABLE_HOLD_INVERSE_PORTRAIT - ]; - - switches.forEach(key => { - const widget = builder.get_object(key.replaceAll('-', '_')); - settings.bind(key, widget, 'active', Gio.SettingsBindFlags.DEFAULT); - }); - } - - /* - * Bind GUI spinbuttons to settings. - */ - _bindSpinbuttons(settings, builder) { - const spinButtons = [ - Settings.WINDOW_GAP, - Settings.SINGLE_SCREEN_GAP, - Settings.SCREEN_TOP_GAP, - Settings.SCREEN_LEFT_GAP, - Settings.SCREEN_RIGHT_GAP, - Settings.SCREEN_BOTTOM_GAP, - Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, - Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, - Settings.INVERSE_TOP_MAXIMIZE_TIMER, - Settings.VERTICAL_PREVIEW_AREA, - Settings.HORIZONTAL_PREVIEW_AREA - ]; - - spinButtons.forEach(key => { - const widget = builder.get_object(key.replaceAll('-', '_')); - settings.bind(key, widget, 'value', Gio.SettingsBindFlags.DEFAULT); - }); - } - - /* - * Bind GUI AdwComboRows to settings. - */ - _bindComboRows(settings, builder) { - const comboRows = [ - Settings.ADAPTIVE_TILING_MOD, - Settings.FAVORITE_LAYOUT_MOD, - Settings.IGNORE_TA_MOD, - Settings.RESTORE_SIZE_ON - ]; - - comboRows.forEach(key => { - const widget = builder.get_object(key.replaceAll('-', '_')); - settings.bind(key, widget, 'selected', Gio.SettingsBindFlags.DEFAULT); - widget.set_selected(settings.get_int(key)); - }); - } - - /* - * Bind GUI color buttons to settings. - */ - _bindColorButtons(settings, builder) { - const switches = [ - Settings.ACTIVE_WINDOW_HINT_COLOR - ]; - - switches.forEach(key => { - const widget = builder.get_object(`${key.replaceAll('-', '_')}_button`); - widget.connect('color-set', () => { - settings.set_string(key, widget.get_rgba().to_string()); - }); - - // initilaize color - const rgba = new Gdk.RGBA(); - rgba.parse(settings.get_string(key)); - widget.set_rgba(rgba); - }); - } - - /* - * Bind radioButtons to settings. - */ - _bindRadioButtons(settings, builder) { - // These 'radioButtons' are basically just used as a 'fake ComboBox' with - // explanations for the different options. So there is just *one* gsetting - // (an int) which saves the current 'selection'. - const radioButtons = [ - { - key: Settings.DYNAMIC_KEYBINDINGS, - rowNames: [ - 'dynamic_keybinding_disabled_row', - 'dynamic_keybinding_window_focus_row', - 'dynamic_keybinding_tiling_state_row', - 'dynamic_keybinding_tiling_state_windows_row', - 'dynamic_keybinding_favorite_layout_row' - ] - }, - { - key: Settings.ACTIVE_WINDOW_HINT, - rowNames: [ - 'active_window_hint_disabled_row', - 'active_window_hint_minimal_row', - 'active_window_hint_always_row' - ] - }, - { - key: Settings.DEFAULT_MOVE_MODE, - rowNames: [ - 'edge_tiling_row', - 'adaptive_tiling_row', - 'favorite_layout_row', - 'ignore_ta_row' - ] - } - ]; - - radioButtons.forEach(({ key, rowNames }) => { - const currActive = settings.get_int(key); - - rowNames.forEach((name, idx) => { - const row = builder.get_object(name.replaceAll('-', '_')); - const checkButton = row.activatable_widget; - checkButton.connect('toggled', () => settings.set_int(key, idx)); - - // Set initial state - if (idx === currActive) - checkButton.activate(); - }); - }); - } - - /* - * Bind keybinding widgets to settings. - */ - _bindKeybindings(settings, builder) { - const shortcuts = Shortcuts.getAllKeys(); - shortcuts.forEach(key => { - const shortcut = builder.get_object(key.replaceAll('-', '_')); - shortcut.initialize(key, settings); - }); - } - - /** - * Sets the visibility of deprecated settings. Those setting aren't visible - * in the GUI unless they have a user set value. That means they aren't - * discoverable through the GUI and need to first be set with the gsetting. - * The normal rows should have the id of: GSETTING_WITH_UNDERSCORES_row. - * ShortcutListeners have the format of GSETTING_WITH_UNDERSCORES. - */ - _setDeprecatedSettings(settings, builder) { - // Keybindings - ['toggle-tiling-popup', 'auto-tile'].forEach(s => { - const isNonDefault = settings.get_strv(s)[0] !== settings.get_default_value(s).get_strv()[0]; - builder.get_object(s.replaceAll('-', '_')).set_visible(isNonDefault); - }); - - // Switches - ['tilegroups-in-app-switcher'].forEach(s => { - const isNonDefault = settings.get_boolean(s) !== settings.get_default_value(s).get_boolean(); - builder.get_object(`${s.replaceAll('-', '_')}_row`).set_visible(isNonDefault); - }); - } - - _addHeaderBarInfoButton(window, settings, builder) { - // Add headerBar button for menu - // TODO: is this a 'reliable' method to access the headerbar? - const page = builder.get_object('general'); - const gtkStack = page - .get_parent() - .get_parent() - .get_parent(); - const adwHeaderBar = gtkStack - .get_next_sibling() - .get_first_child() - .get_first_child() - .get_first_child(); - - adwHeaderBar.pack_start(builder.get_object('info_menu')); - - // Setup menu actions - const actionGroup = new Gio.SimpleActionGroup(); - window.insert_action_group('prefs', actionGroup); - - const bugReportAction = new Gio.SimpleAction({ name: 'open-bug-report' }); - bugReportAction.connect('activate', this._openBugReport.bind(this, window)); - actionGroup.add_action(bugReportAction); - - const userGuideAction = new Gio.SimpleAction({ name: 'open-user-guide' }); - userGuideAction.connect('activate', this._openUserGuide.bind(this, window)); - actionGroup.add_action(userGuideAction); - - const changelogAction = new Gio.SimpleAction({ name: 'open-changelog' }); - changelogAction.connect('activate', this._openChangelog.bind(this, window)); - actionGroup.add_action(changelogAction); - - const licenseAction = new Gio.SimpleAction({ name: 'open-license' }); - licenseAction.connect('activate', this._openLicense.bind(this, window)); - actionGroup.add_action(licenseAction); - - const hiddenSettingsAction = new Gio.SimpleAction({ name: 'open-hidden-settings' }); - hiddenSettingsAction.connect('activate', this._openHiddenSettings.bind(this, window, builder)); - actionGroup.add_action(hiddenSettingsAction); - - // Button to return to main settings page - const returnButton = builder.get_object('hidden_settings_return_button'); - returnButton.connect('clicked', () => window.close_subpage()); - } - - _openBugReport(window) { - Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/issues', Gdk.CURRENT_TIME); - } - - _openUserGuide(window) { - Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/wiki', Gdk.CURRENT_TIME); - } - - _openChangelog(window) { - Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/blob/main/CHANGELOG.md', Gdk.CURRENT_TIME); - } - - _openLicense(window) { - Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/blob/main/LICENSE', Gdk.CURRENT_TIME); - } - - _openHiddenSettings(window, builder) { - const hiddenSettingsPage = builder.get_object('hidden_settings'); - window.present_subpage(hiddenSettingsPage); - } -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/schemas/gschemas.compiled b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/schemas/gschemas.compiled deleted file mode 100644 index 1735f478cf251d6af34230db4c09eee1bc9f0991..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5813 zcmaKwdyG`o9mg-0RX`pq4_!oLv4E>^cUgI@6)YAkTLHVG%fnXPyE}JxZkd@o+`0SG zteP5IY(;4k8dEhPO>Buuq&6f-(uO_+T7%tKX~oo5i5mWp)-+9}O^p3~&popo_nv#6zw_D+TfHdoaQ8+P!G9+g{; z@%%2L27NKO#Ntv|m;$DPX=SKIUuH2KF2@Xh3p2qLK<&N~%(0jYmt!8k>n*Nd0jI%_UjF-c-ymCpnQZVI^OUk@CY zFTDW21zrp0?|5RLeCfIP9dH`FbKGf?FI|g20DlLZS+sh(d}+07KYRdu^5n5lzO?*f z@T*|ww+{YZzVsaYci|7f*#mVykS~2T{)EZY4LtqGW5e>LRsROq1^=FS>Y#k-%kf*` zHZbd^p-bdT&%@8dz2NrCzcEX`^i2G{@IJ8m#kHpX((1PZ@ImnW;)njK^wLxDkHIHF z)8v8ojVE7v3VuDj5Nv*X>QVX9>i;&l9pt_? z;m7i&Rc;!-9~}APDl?AK%4avc7tFb8{CcIAmcJi<8GQ87yjuCv>i?7QFj%?lpL^s> zFT}q9e+rsjc=51&X|=14i9HuQzxL5K`O=EF7I+QV@bkx?moKgU-wxjcQh(m{l6+~^ zClBudPhEKWLHW|k=Ky>NJbohjgM8`P_`~pNP+a?@HS6Ajm$SI6yJTxx>7^Bit?*{> z%wtPt$d^{T2H+uZZ0NyDwT4R9;O~ZyfV%b1?pJzg#o=4?VEqp7eeQ9;Qd}*ccfPL`BhZ8&HOE1FT3-1HNnbwEo zODld3z=y!uGealjOJ9M15Y1VB6XE7Ri^s2EPOL!5!--9FZ?=<~uwDwpd?U{$6+=xMkDS50qZo%p>?9ct0FJ zAYXbu>4)Ldpga4*_vA}Y$3F*u4DPh~ODlgeb80}{+pn4VBCYYNha13MHodgcx4>(_ z{%f-)e`yn+a0hs6*Q7gCuC(S?9_|J0HXmu_vm4$6wpw3W{(ks5kos)hGs;I=<9iH# z0~|hj#XR}aN`DUi7;G!H%lg^`Yrvmw>bp|urB%;*cp=zs(@UFn!E3+{>r2aTgWJK~ z)|Zx_hO=P7ocB#UNGncu!+XI`PcDC3=CS-bcrG|@eQEhi;T7P7^`+&v!kfWK>r2b;fPL^=>r2ZYfQP`A zBR@0io3zH|Dfn6NJDXlw=?}q&!B6g;_8+xZT5)?4J_QE%{cWRsX{}4=;Pc=$n~${e zVbGi!aIv!}8Ar6{ZynqME^41+`d@kyekzgY~NS*TGDUo z*PbZs%@=65>*ez{N7E9@$#{j>?eim@;Yq>CJ;UIbI%;1VY3Jy1E-$Nch`VWQ+2E3u z-rG(sA3x*Uz9IXH9w;xjyost!*4~ zVk!>ZZm%zlg4lO6-eA}pE3J9xr^qib9K}E~uC2%Vus>((F%q?!D)!UTJTdW!TdIFc zW&Ld|RkVOOv7zs!`n+5h6UQG=9As&gmvOs&FYcvs#d_L)_A>q6V8LZf>Di{oJp6Pel`n-r_R)$U;{@pX68Jxljb zmOFEwV(Dd%OYWy6$rntV^DMv@rrKVi7U?=m@{MPC?c3Vu= zv9bHx=$%b5q;|7~M^TVUu@x2kIHnJhVJ4pk3VlQ6TWQ6XUcS^Tt5Uh%$Wp18uI4LV zjh_k%#SPqNH`9j1i;Dfbe4Vc-v-&=6;#%!8TYRZ1Hzef^=DcjscA1dcuYvnn_Xe17 - - - - - - - true - - - false - - - true - - - false - - - - 0 - - - - 1 - - - '' - - - 5 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - false - - - true - - - - - - [] - - - [] - - - [] - - - [] - - - Up','KP_5']]]> - - - [] - - - [] - - - Down']]]> - - - [] - - - KP_8']]]> - - - KP_2']]]> - - - Left','KP_4']]]> - - - Right','KP_6']]]> - - - KP_7']]]> - - - KP_9']]]> - - - KP_1']]]> - - - KP_3']]]> - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - - - - true - - - false - - - [] - - - -1 - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - [] - - - - - - false - - - true - - - true - - - false - - - - 0 - - - false - - - false - - - - 1 - - - - 2 - - - - 0 - - - 15 - - - 15 - - - 600 - - - false - - - false - - - - 0 - - - [] - - - [] - - - -1 - - - - [] - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/common.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/common.js deleted file mode 100644 index 72bef63..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/common.js +++ /dev/null @@ -1,423 +0,0 @@ -/** - * Helper classes / enums for the settings.xml used in the extension files - * *and* prefs files - */ - -/** - * A Singleton providing access to the settings. - */ -export class Settings { - static _settings; - static ENABLE_TILING_POPUP = 'enable-tiling-popup'; - static POPUP_ALL_WORKSPACES = 'tiling-popup-all-workspace'; - static RAISE_TILE_GROUPS = 'enable-raise-tile-group'; - static TILEGROUPS_IN_APP_SWITCHER = 'tilegroups-in-app-switcher'; - static WINDOW_GAP = 'window-gap'; - static SINGLE_SCREEN_GAP = 'single-screen-gap'; - static SCREEN_TOP_GAP = 'screen-top-gap'; - static SCREEN_LEFT_GAP = 'screen-left-gap'; - static SCREEN_RIGHT_GAP = 'screen-right-gap'; - static SCREEN_BOTTOM_GAP = 'screen-bottom-gap'; - static MAXIMIZE_WITH_GAPS = 'maximize-with-gap'; - static DYNAMIC_KEYBINDINGS = 'dynamic-keybinding-behavior'; - static ACTIVE_WINDOW_HINT = 'active-window-hint'; - static ACTIVE_WINDOW_HINT_COLOR = 'active-window-hint-color'; - static ACTIVE_WINDOW_HINT_BORDER_SIZE = 'active-window-hint-border-size'; - static ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE = 'active-window-hint-inner-border-size'; - static SHOW_LAYOUT_INDICATOR = 'show-layout-panel-indicator'; - static ENABLE_ADV_EXP_SETTINGS = 'enable-advanced-experimental-features'; - static DISABLE_TILE_GROUPS = 'disable-tile-groups'; - static ENABLE_TILE_ANIMATIONS = 'enable-tile-animations'; - static ENABLE_UNTILE_ANIMATIONS = 'enable-untile-animations'; - static FAVORITE_LAYOUTS = 'favorite-layouts'; - static DEFAULT_MOVE_MODE = 'default-move-mode'; - static LOW_PERFORMANCE_MOVE_MODE = 'low-performance-move-mode'; - static MONITOR_SWITCH_GRACE_PERIOD = 'monitor-switch-grace-period'; - static ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT = 'adapt-edge-tiling-to-favorite-layout'; - static ADAPTIVE_TILING_MOD = 'move-adaptive-tiling-mod'; - static FAVORITE_LAYOUT_MOD = 'move-favorite-layout-mod'; - static IGNORE_TA_MOD = 'ignore-ta-mod'; - static VERTICAL_PREVIEW_AREA = 'vertical-preview-area'; - static HORIZONTAL_PREVIEW_AREA = 'horizontal-preview-area'; - static INVERSE_TOP_MAXIMIZE_TIMER = 'toggle-maximize-tophalf-timer'; - static ENABLE_HOLD_INVERSE_LANDSCAPE = 'enable-hold-maximize-inverse-landscape'; - static ENABLE_HOLD_INVERSE_PORTRAIT = 'enable-hold-maximize-inverse-portrait'; - static RESTORE_SIZE_ON = 'restore-window-size-on'; - - static initialize(gioSettings) { - this._settings = gioSettings; - } - - static destroy() { - this._settings = null; - } - - /** - * @returns {Gio.Settings} the Gio.Settings object. - */ - static getGioObject() { - return this._settings; - } - - /** - * Listens for the change of a setting. - * - * @param {string} key a settings key. - * @param {*} func function to call when the setting changed. - */ - static changed(key, func) { - return this._settings.connect(`changed::${key}`, func); - } - - static disconnect(id) { - this._settings.disconnect(id); - } - - /** - * @returns {string[]} the settings keys except the ones for shortcuts. - */ - static getAllKeys() { - return [ - this.ENABLE_TILING_POPUP, - this.POPUP_ALL_WORKSPACES, - this.RAISE_TILE_GROUPS, - this.TILEGROUPS_IN_APP_SWITCHER, - this.WINDOW_GAP, - this.SINGLE_SCREEN_GAP, - this.SCREEN_TOP_GAP, - this.SCREEN_LEFT_GAP, - this.SCREEN_RIGHT_GAP, - this.SCREEN_BOTTOM_GAP, - this.MAXIMIZE_WITH_GAPS, - this.DYNAMIC_KEYBINDINGS, - this.ACTIVE_WINDOW_HINT, - this.ACTIVE_WINDOW_HINT_COLOR, - this.ACTIVE_WINDOW_HINT_BORDER_SIZE, - this.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, - this.SHOW_LAYOUT_INDICATOR, - this.ENABLE_ADV_EXP_SETTINGS, - this.DISABLE_TILE_GROUPS, - this.ENABLE_TILE_ANIMATIONS, - this.ENABLE_UNTILE_ANIMATIONS, - this.FAVORITE_LAYOUTS, - this.DEFAULT_MOVE_MODE, - this.LOW_PERFORMANCE_MOVE_MODE, - this.MONITOR_SWITCH_GRACE_PERIOD, - this.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT, - this.ADAPTIVE_TILING_MOD, - this.FAVORITE_LAYOUT_MOD, - this.IGNORE_TA_MOD, - this.VERTICAL_PREVIEW_AREA, - this.HORIZONTAL_PREVIEW_AREA, - this.INVERSE_TOP_MAXIMIZE_TIMER, - this.ENABLE_HOLD_INVERSE_LANDSCAPE, - this.ENABLE_HOLD_INVERSE_PORTRAIT, - this.RESTORE_SIZE_ON - ]; - } - - /** - * Getters - */ - - static getEnum(key) { - return this._settings.get_enum(key); - } - - static getString(key) { - return this._settings.get_string(key); - } - - static getStrv(key) { - return this._settings.get_strv(key); - } - - static getInt(key) { - return this._settings.get_int(key); - } - - static getBoolean(key) { - return this._settings.get_boolean(key); - } - - static getValue(key) { - return this._settings.get_value(key); - } - - static getUserValue(key) { - return this._settings.get_user_value(key); - } - - /** - * Setters - */ - - static setEnum(key, value) { - this._settings.set_enum(key, value); - } - - static setString(key, value) { - this._settings.set_string(key, value); - } - - static setStrv(key, value) { - this._settings.set_strv(key, value); - } - - static setInt(key, value) { - this._settings.set_int(key, value); - } - - static setBoolean(key, value) { - this._settings.set_boolean(key, value); - } - - static setValue(key, value) { - return this._settings.set_value(key, value); - } - - static reset(key) { - this._settings.reset(key); - } -} - -/** - * A Singleton providing access to the shortcut keys except the - * ones related to the Layouts. - */ -export class Shortcuts { - static TOGGLE_POPUP = 'toggle-tiling-popup'; - static EDIT_MODE = 'tile-edit-mode'; - static AUTO_FILL = 'auto-tile'; - static ALWAYS_ON_TOP = 'toggle-always-on-top'; - static MAXIMIZE = 'tile-maximize'; - static MAXIMIZE_V = 'tile-maximize-vertically'; - static MAXIMIZE_H = 'tile-maximize-horizontally'; - static RESTORE_WINDOW = 'restore-window'; - static CENTER_WINDOW = 'center-window'; - static TOP = 'tile-top-half'; - static BOTTOM = 'tile-bottom-half'; - static LEFT = 'tile-left-half'; - static RIGHT = 'tile-right-half'; - static TOP_LEFT = 'tile-topleft-quarter'; - static TOP_RIGHT = 'tile-topright-quarter'; - static BOTTOM_LEFT = 'tile-bottomleft-quarter'; - static BOTTOM_RIGHT = 'tile-bottomright-quarter'; - static TOP_IGNORE_TA = 'tile-top-half-ignore-ta'; - static BOTTOM_IGNORE_TA = 'tile-bottom-half-ignore-ta'; - static LEFT_IGNORE_TA = 'tile-left-half-ignore-ta'; - static RIGHT_IGNORE_TA = 'tile-right-half-ignore-ta'; - static TOP_LEFT_IGNORE_TA = 'tile-topleft-quarter-ignore-ta'; - static TOP_RIGHT_IGNORE_TA = 'tile-topright-quarter-ignore-ta'; - static BOTTOM_LEFT_IGNORE_TA = 'tile-bottomleft-quarter-ignore-ta'; - static BOTTOM_RIGHT_IGNORE_TA = 'tile-bottomright-quarter-ignore-ta'; - static DEBUGGING = 'debugging-show-tiled-rects'; - static DEBUGGING_FREE_RECTS = 'debugging-free-rects'; - - /** - * @returns {string[]} the settings keys for the shortcuts in the same - * order as they appear in the preference window. - */ - static getAllKeys() { - return [ - this.TOGGLE_POPUP, - this.EDIT_MODE, - this.AUTO_FILL, - this.ALWAYS_ON_TOP, - this.MAXIMIZE, - this.MAXIMIZE_V, - this.MAXIMIZE_H, - this.RESTORE_WINDOW, - this.CENTER_WINDOW, - this.TOP, - this.BOTTOM, - this.LEFT, - this.RIGHT, - this.TOP_LEFT, - this.TOP_RIGHT, - this.BOTTOM_LEFT, - this.BOTTOM_RIGHT, - this.TOP_IGNORE_TA, - this.BOTTOM_IGNORE_TA, - this.LEFT_IGNORE_TA, - this.RIGHT_IGNORE_TA, - this.TOP_LEFT_IGNORE_TA, - this.TOP_RIGHT_IGNORE_TA, - this.BOTTOM_LEFT_IGNORE_TA, - this.BOTTOM_RIGHT_IGNORE_TA, - this.DEBUGGING, - this.DEBUGGING_FREE_RECTS - ]; - } -} - -// Enums: -export class RestoreOn { - static ON_GRAB_START = 0; // Grab Start - static ON_GRAB_END = 1; // 'Grab End' -} - -export class DynamicKeybindings { - // Order comes from prefs - static DISABLED = 0; - static FOCUS = 1; - static TILING_STATE = 2; - static TILING_STATE_WINDOWS = 3; - static FAVORITE_LAYOUT = 4; -} - -export class MoveModes { - // Order comes from prefs - static EDGE_TILING = 0; - static ADAPTIVE_TILING = 1; - static FAVORITE_LAYOUT = 2; - static IGNORE_TA = 3; -} - -export class Orientation { - static H = 1; - static V = 2; -} - -export class Direction { - static N = 1; - static E = 2; - static S = 4; - static W = 8; - - static opposite(dir) { - let opposite = 0; - if (dir & this.N) - opposite |= this.S; - if (dir & this.S) - opposite |= this.N; - if (dir & this.W) - opposite |= this.E; - if (dir & this.E) - opposite |= this.W; - - return opposite; - } -} - -// Classes for the layouts: -// See src/prefs/layoutsPrefs.js for details on layouts. -export class Layout { - /** - * @param {object} layout is the parsed object from the layouts file. - */ - constructor(layout = null) { - this._name = layout?._name ?? ''; - this._items = layout?._items ?? []; - } - - /** - * @returns {string} - */ - getName() { - return this._name; - } - - /** - * @param {string} name - */ - setName(name) { - this._name = name; - } - - /** - * @param {number} index - * @returns {LayoutItem} - */ - getItem(index) { - return this._items[index]; - } - - /** - * @param {LayoutItem|null} item - * @returns {LayoutItem} the added item. - */ - addItem(item = null) { - item = item ?? new LayoutItem(); - this._items.push(item); - return item; - } - - /** - * @param {number} index - * @returns {LayoutItem|null} the removed item. - */ - removeItem(index) { - return this._items.splice(index, 1)[0]; - } - - /** - * @param {boolean} filterOutEmptyRects - * @returns {LayoutItem[]} - */ - getItems(filterOutEmptyRects = true) { - return filterOutEmptyRects - ? this._items.filter(i => Object.keys(i.rect).length === 4) - : this._items; - } - - /** - * @param {LayoutItem[]} items - */ - setItems(items) { - this._items = items; - } - - /** - * @param {boolean} filterOutEmptyRects - * @returns {number} - */ - getItemCount(filterOutEmptyRects = false) { - return filterOutEmptyRects - ? this.getItems().length - : this._items.length; - } - - /** - * @returns {[boolean, string]} whether the layout has valid rects and - * a potential error message. - */ - validate() { - const rects = this.getItems().map(i => i.rect); - if (!rects.length) - return [false, 'No valid rectangles defined.', -1]; - - const getOverlapArea = (r1, r2) => { - return Math.max(0, Math.min(r1.x + r1.width, r2.x + r2.width) - Math.max(r1.x, r2.x)) * - Math.max(0, Math.min(r1.y + r1.height, r2.y + r2.height) - Math.max(r1.y, r2.y)); - }; - - for (let i = 0; i < rects.length; i++) { - const rect = rects[i]; - - if (rect.width <= 0 || rect.width > 1) - return [false, `Rectangle ${i} has an invalid width.`, i]; - - if (rect.height <= 0 || rect.height > 1) - return [false, `Rectangle ${i} has an invalid height.`, i]; - - if (rect.x < 0 || rect.y < 0 || rect.x + rect.width > 1 || rect.y + rect.height > 1) - return [false, `Rectangle ${i} extends beyond the screen.`, i]; - - for (let j = i + 1; j < rects.length; j++) { - if (getOverlapArea(rect, rects[j]) !== 0) - return [false, `Rectangles ${i} and ${j} overlap.`, j]; - } - } - - return [true, '', -1]; - } -} - -var LayoutItem = class LayoutItem { - constructor() { - this.rect = {}; - this.appId = null; - this.loopType = null; - } -}; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/gi.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/gi.js deleted file mode 100644 index 937881a..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/gi.js +++ /dev/null @@ -1,9 +0,0 @@ -export { default as Atk } from 'gi://Atk'; -export { default as Clutter } from 'gi://Clutter'; -export { default as Gio } from 'gi://Gio'; -export { default as GLib } from 'gi://GLib'; -export { default as GObject } from 'gi://GObject'; -export { default as Meta } from 'gi://Meta'; -export { default as Mtk } from 'gi://Mtk'; -export { default as Shell } from 'gi://Shell'; -export { default as St } from 'gi://St'; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs.js deleted file mode 100644 index 30f203e..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs.js +++ /dev/null @@ -1,4 +0,0 @@ -export { - ExtensionPreferences, - gettext as _ -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs/gi.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs/gi.js deleted file mode 100644 index 974c9c2..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/prefs/gi.js +++ /dev/null @@ -1,6 +0,0 @@ -export { default as Adw } from 'gi://Adw'; -export { default as Gdk } from 'gi://Gdk'; -export { default as Gio } from 'gi://Gio'; -export { default as GLib } from 'gi://GLib'; -export { default as GObject } from 'gi://GObject'; -export { default as Gtk } from 'gi://Gtk'; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/shell.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/shell.js deleted file mode 100644 index cd0b07f..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/shell.js +++ /dev/null @@ -1,11 +0,0 @@ -export { - Extension, - gettext as _ -} from 'resource:///org/gnome/shell/extensions/extension.js'; - -export * as AltTab from 'resource:///org/gnome/shell/ui/altTab.js'; -export * as Main from 'resource:///org/gnome/shell/ui/main.js'; -export * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -export * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -export * as SwitcherPopup from 'resource:///org/gnome/shell/ui/switcherPopup.js'; -export * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js'; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/altTab.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/altTab.js deleted file mode 100644 index ba8e793..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/altTab.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Meta } from '../gi.js'; - -export const baseIconSizes = [96, 64, 48, 32, 22]; -export const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds - -export function getWindows(workspace) { - // We ignore skip-taskbar windows in switchers, but if they are attached - // to their parent, their position in the MRU list may be more appropriate - // than the parent; so start with the complete list ... - let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, workspace); - // ... map windows to their parent where appropriate ... - return windows.map(w => { - return w.is_attached_dialog() ? w.get_transient_for() : w; - // ... and filter out skip-taskbar windows and duplicates - }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) === i); -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/windowManager.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/windowManager.js deleted file mode 100644 index 06b5db8..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/dependencies/unexported/windowManager.js +++ /dev/null @@ -1 +0,0 @@ -export const WINDOW_ANIMATION_TIME = 250; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/activeWindowHint.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/activeWindowHint.js deleted file mode 100644 index f0943ea..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/activeWindowHint.js +++ /dev/null @@ -1,333 +0,0 @@ -import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; -import { Main } from '../dependencies/shell.js'; - -import { Settings } from '../common.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -export default class ActiveWindowHintHandler { - constructor() { - // On a fresh install no color is set for the hint yet. Use the bg color - // from the tile preview style by using a temporary widget. - if (Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR) === '') { - const widget = new St.Widget({ style_class: 'tile-preview' }); - global.stage.add_child(widget); - - const color = widget.get_theme_node().get_background_color(); - const { red, green, blue } = color; - - Settings.setString(Settings.ACTIVE_WINDOW_HINT_COLOR, `rgb(${red},${green},${blue})`); - - widget.destroy(); - } - - this._hint = null; - this._settingsId = 0; - - this._setupHint(); - - this._settingsId = Settings.changed(Settings.ACTIVE_WINDOW_HINT, - () => this._setupHint()); - } - - destroy() { - Settings.disconnect(this._settingsId); - this._hint?.destroy(); - this._hint = null; - } - - _setupHint() { - switch (Settings.getInt(Settings.ACTIVE_WINDOW_HINT)) { - case 0: // Disabled - this._hint?.destroy(); - this._hint = null; - break; - case 1: // Minimal - this._hint?.destroy(); - this._hint = new MinimalHint(); - break; - case 2: // Always - this._hint?.destroy(); - this._hint = new AlwaysHint(); - } - } -} - -const Hint = GObject.registerClass( -class ActiveWindowHint extends St.Widget { - _init() { - super._init(); - - this._color = Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR); - this._borderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE); - this._innerBorderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE); // 'Inner border' to cover rounded corners - this._settingsIds = []; - - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { - this._color = Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR); - })); - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, () => { - this._borderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE); - })); - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, () => { - this._innerBorderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE); - })); - - global.window_group.add_child(this); - } - - destroy() { - this._settingsIds.forEach(id => Settings.disconnect(id)); - super.destroy(); - } -}); - -const MinimalHint = GObject.registerClass( -class MinimalActiveWindowHint extends Hint { - _init() { - super._init(); - - this._windowClone = null; - - this._updateStyle(); - - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { - this._updateStyle(); - })); - - global.workspace_manager.connectObject('workspace-switched', - () => this._onWsSwitched(), this); - } - - destroy() { - this._reset(); - super.destroy(); - } - - _reset() { - if (this._laterId) { - global.compositor.get_laters().remove(this._laterId); - delete this._laterId; - } - this._windowClone?.destroy(); - this._windowClone = null; - this.hide(); - } - - _updateStyle() { - this.set_style(`background-color: ${this._color};`); - } - - _onWsSwitched() { - // Reset in case multiple workspaces are switched at once. - this._reset(); - - // If we are in the overview, it's likely the user actively chose - // a window to focus. So the hint is unnecessary. - if (Main.overview.visible) - return; - - const window = global.display.focus_window; - if (!window) - return; - - // Maximized or fullscreen windows don't require a hint since they - // cover the entire screen. - if (window.is_fullscreen() || Twm.isMaximized(window)) - return; - - // Now figure out if the focused window is easily identifiable by - // checking (in stacking order) if all other windows are being - // overlapped by higher windows. If a window is not overlapped, the - // focused window is ambiguous. - const windows = Twm.getWindows(); - const overlapping = windows.splice(windows.indexOf(window), 1); - - const notOverlappedWindowExists = windows.some(w => { - if (!overlapping.some(o => o.get_frame_rect().overlap(w.get_frame_rect()))) - return true; - - overlapping.push(w); - return false; - }); - - if (notOverlappedWindowExists) - this._giveHint(window); - } - - _giveHint(window) { - this._scaleClone(window); - this._rippleFade(window); - } - - _scaleClone(window) { - const actor = window.get_compositor_private(); - if (!actor) - return; - - const { x, y, width, height } = actor; - const scaleAmount = 15; - this._windowClone = new Clutter.Clone({ - source: actor, - x: x - scaleAmount, - y: y - scaleAmount, - width: width + 2 * scaleAmount, - height: height + 2 * scaleAmount - }); - global.window_group.insert_child_above(this._windowClone, actor); - - this._windowClone.ease({ - x, y, width, height, - delay: 250, - duration: 250, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - // May already have been destroyed by a reset - this._windowClone?.destroy(); - this._windowClone = null; - } - }); - } - - _rippleFade(window) { - const actor = window.get_compositor_private(); - if (!actor) - return; - - if (!this._laterId) { - this._laterId = global.compositor.get_laters().add( - Meta.LaterType.BEFORE_REDRAW, - () => { - global.window_group.set_child_below_sibling(this, actor); - delete this._laterId; - return false; - } - ); - } - - const { x, y, width, height } = window.get_frame_rect(); - this.set({ x, y, width, height }); - - this.set_opacity(255); - this.show(); - - const rippleSize = 30; - this.ease({ - x: x - rippleSize, - y: y - rippleSize, - width: width + 2 * rippleSize, - height: height + 2 * rippleSize, - opacity: 0, - delay: 250, - duration: 350, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => this.hide() - }); - } -}); - -// TODO a solid bg color looks better than a border when launching an app since -// the border will appear before the window is fully visible. However there was -// an issue with global.window_group.set_child_below_sibling not putting the hint -// below the window for some reason. laters-add solved it but I don't know -// why. So as to not potentially cover the entire window's content use the border -// style until I figure out if laters-add is the proper solution... -const AlwaysHint = GObject.registerClass( -class AlwaysActiveWindowHint extends Hint { - _init() { - super._init(); - - this._window = null; - this._signalIds = []; - - this._updateGeometry(); - this._updateStyle(); - - global.display.connectObject('notify::focus-window', - () => this._updateGeometry(), this); - - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { - this._updateStyle(); - this._updateGeometry(); - })); - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, () => { - this._updateStyle(); - this._updateGeometry(); - })); - this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, () => { - this._updateStyle(); - this._updateGeometry(); - })); - } - - destroy() { - this._reset(); - super.destroy(); - } - - vfunc_hide() { - this._cancelShowLater(); - super.vfunc_hide(); - } - - _reset() { - this._cancelShowLater(); - this._signalIds.forEach(id => this._window.disconnect(id)); - this._signalIds = []; - this._window = null; - } - - _cancelShowLater() { - if (!this._showLater) - return; - - - global.compositor.get_laters().remove(this._showLater); - delete this._showLater; - } - - _updateGeometry() { - this._reset(); - - const window = global.display.focus_window; - const allowTypes = [Meta.WindowType.NORMAL, Meta.WindowType.DIALOG, Meta.WindowType.MODAL_DIALOG]; - if (!window || !allowTypes.includes(window.get_window_type())) { - this.hide(); - return; - } - - this._window = window; - this._signalIds.push(window.connect('position-changed', () => this._updateGeometry())); - this._signalIds.push(window.connect('size-changed', () => this._updateGeometry())); - - // Don't show hint on maximzed/fullscreen windows - if (window.is_fullscreen() || Twm.isMaximized(window)) { - this.hide(); - return; - } - - const { x, y, width, height } = window.get_frame_rect(); - this.set({ x, y, width, height }); - - const actor = window.get_compositor_private(); - - if (!actor || this._showLater) - return; - - this._showLater = global.compositor.get_laters().add( - Meta.LaterType.IDLE, - () => { - global.window_group.set_child_below_sibling(this, actor); - this.show(); - delete this._showLater; - return false; - } - ); - } - - _updateStyle() { - this.set_style(` - border: ${this._innerBorderSize}px solid ${this._color}; - outline: ${this._borderSize}px solid ${this._color}; - `); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/altTab.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/altTab.js deleted file mode 100644 index 68d4d79..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/altTab.js +++ /dev/null @@ -1,486 +0,0 @@ -import { - Atk, - Clutter, - Gio, - GLib, - GObject, - Meta, - Shell, - St -} from '../dependencies/gi.js'; -import { - AltTab, - Extension, - Main, - SwitcherPopup -} from '../dependencies/shell.js'; -import { - baseIconSizes, - APP_ICON_HOVER_TIMEOUT -} from '../dependencies/unexported/altTab.js'; - -import { Settings } from '../common.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -/** - * Optionally, override GNOME's altTab / appSwitcher to group tileGroups - */ -export default class AltTabOverride { - constructor() { - if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) - this._overrideNativeAppSwitcher(); - - this._settingsId = Settings.changed(Settings.TILEGROUPS_IN_APP_SWITCHER, () => { - if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) - this._overrideNativeAppSwitcher(); - else - this._restoreNativeAppSwitcher(); - }); - } - - destroy() { - Settings.disconnect(this._settingsId); - this._restoreNativeAppSwitcher(); - } - - _overrideNativeAppSwitcher() { - Main.wm.setCustomKeybindingHandler( - 'switch-applications', - Shell.ActionMode.NORMAL, - this._startSwitcher.bind(this) - ); - } - - _restoreNativeAppSwitcher() { - Main.wm.setCustomKeybindingHandler( - 'switch-applications', - Shell.ActionMode.NORMAL, - Main.wm._startSwitcher.bind(Main.wm) - ); - } - - /** - * Copy-pasta from windowManager.js. Removed unused stuff... - * - * @param {*} display - - * @param {*} window - - * @param {*} binding - - */ - _startSwitcher(display, window, binding) { - if (Main.wm._workspaceSwitcherPopup !== null) - Main.wm._workspaceSwitcherPopup.destroy(); - - const tabPopup = new TilingAppSwitcherPopup(); - - if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) - tabPopup.destroy(); - } -} - -export const TilingAppSwitcherPopup = GObject.registerClass( -class TilingAppSwitcherPopup extends AltTab.AppSwitcherPopup { - _init() { - SwitcherPopup.SwitcherPopup.prototype._init.call(this); - - const settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' }); - const workspace = settings.get_boolean('current-workspace-only') - ? global.workspace_manager.get_active_workspace() - : null; - const windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace); - - this._switcherList = new TilingAppSwitcher(this, windows); - this._items = this._switcherList.icons; - } - - // Called when closing an entire app / tileGroup - _quitApplication(index) { - const item = this._items[index]; - if (!item) - return; - - item.cachedWindows.forEach(w => w.delete(global.get_current_time())); - item.cachedWindows = []; - this._switcherList._removeIcon(item); - } - - // Called when closing a window with the thumbnail switcher - // meaning that .cachedWindow of an item was updated via signals - _windowRemoved(thumbnailSwitcher, n) { - const item = this._items[this._selectedIndex]; - if (!item) - return; - - if (item.cachedWindows.length) { - const newIndex = Math.min(n, item.cachedWindows.length - 1); - this._select(this._selectedIndex, newIndex); - } - - item.updateAppIcons(); - } -}); - -export const TilingAppSwitcher = GObject.registerClass( -class TilingAppSwitcher extends SwitcherPopup.SwitcherList { - _init(altTabPopup, windows) { - // Don't make the SwitcherButtons squares since 1 SwitcherButton - // may contain multiple AppIcons for a tileGroup. - super._init(false); - - this.icons = []; - this._arrows = []; - this._apps = []; - this._altTabPopup = altTabPopup; - this._delayedHighlighted = -1; - this._mouseTimeOutId = 0; - - const winTracker = Shell.WindowTracker.get_default(); - let groupedWindows; - - // Group windows based on their tileGroup, if tileGroup.length > 1. - // Otherwise group them based on their respective apps. - if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) { - groupedWindows = windows.reduce((allGroups, w) => { - for (const group of allGroups) { - if (w.isTiled && Twm.getTileGroupFor(w).length > 1) { - if (Twm.getTileGroupFor(w).includes(group[0])) { - group.push(w); - return allGroups; - } - } else if ((!group[0].isTiled || group[0].isTiled && Twm.getTileGroupFor(group[0]).length <= 1) && - winTracker.get_window_app(group[0]) === winTracker.get_window_app(w)) { - group.push(w); - return allGroups; - } - } - const newGroup = [w]; - allGroups.push(newGroup); - return allGroups; - }, []); - - // Group windows based on apps - } else { - groupedWindows = windows.reduce((allGroups, w) => { - for (const group of allGroups) { - if (winTracker.get_window_app(group[0]) === winTracker.get_window_app(w)) { - group.push(w); - return allGroups; - } - } - - const newGroup = [w]; - allGroups.push(newGroup); - return allGroups; - }, []); - } - - // Construct the AppIcons and add them to the popup. - groupedWindows.forEach(group => { - const item = new AppSwitcherItem(group); - item.connect('all-icons-removed', () => this._removeIcon(item)); - this._addIcon(item); - }); - - // Listen for the app stop state in case the app got closed outside - // of the app switcher along with closing via the app switcher - const allApps = windows.map(w => winTracker.get_window_app(w)); - this._apps = [...new Set(allApps)]; - this._stateChangedIds = this._apps.map(app => app.connect('notify::state', () => { - if (app.state !== Shell.AppState.RUNNING) - this.icons.forEach(item => item.removeApp(app)); - })); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - _onDestroy() { - if (this._mouseTimeOutId !== 0) - GLib.source_remove(this._mouseTimeOutId); - - this._stateChangedIds?.forEach((id, index) => this._apps[index].disconnect(id)); - this._stateChangedIds = []; - this._apps = []; - } - - _setIconSize() { - let j = 0; - while (this._items.length > 1 && this._items[j].style_class !== 'item-box') - j++; - - let themeNode = this._items[j].get_theme_node(); - this._list.ensure_style(); - - let iconPadding = themeNode.get_horizontal_padding(); - let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); - let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1); - let iconSpacing = labelNaturalHeight + iconPadding + iconBorder; - let totalSpacing = this._list.spacing * (this._items.length - 1); - - // We just assume the whole screen here due to weirdness happening with the passed width - let primary = Main.layoutManager.primaryMonitor; - let parentPadding = this.get_parent().get_theme_node().get_horizontal_padding(); - let availWidth = primary.width - parentPadding - this.get_theme_node().get_horizontal_padding(); - - let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - let iconSizes = baseIconSizes.map(s => s * scaleFactor); - let iconSize = baseIconSizes[0]; - - if (this._items.length > 1) { - for (let i = 0; i < baseIconSizes.length; i++) { - iconSize = baseIconSizes[i]; - let height = iconSizes[i] + iconSpacing; - let w = height * this._items.length + totalSpacing; - if (w <= availWidth) - break; - } - } - - this._iconSize = iconSize; - - for (let i = 0; i < this.icons.length; i++) { - // eslint-disable-next-line eqeqeq - if (this.icons[i].icon != null) - break; - this.icons[i].set_size(iconSize); - } - } - - vfunc_get_preferred_height(forWidth) { - if (!this._iconSize) - this._setIconSize(); - - return super.vfunc_get_preferred_height(forWidth); - } - - vfunc_allocate(box) { - // Allocate the main list items - super.vfunc_allocate(box); - - let contentBox = this.get_theme_node().get_content_box(box); - - let arrowHeight = Math.floor(this.get_theme_node().get_padding(St.Side.BOTTOM) / 3); - let arrowWidth = arrowHeight * 2; - - // Now allocate each arrow underneath its item - let childBox = new Clutter.ActorBox(); - for (let i = 0; i < this._items.length; i++) { - let itemBox = this._items[i].allocation; - childBox.x1 = contentBox.x1 + Math.floor(itemBox.x1 + (itemBox.x2 - itemBox.x1 - arrowWidth) / 2); - childBox.x2 = childBox.x1 + arrowWidth; - childBox.y1 = contentBox.y1 + itemBox.y2 + arrowHeight; - childBox.y2 = childBox.y1 + arrowHeight; - this._arrows[i].allocate(childBox); - } - } - - // We override SwitcherList's _onItemMotion method to delay - // activation when the thumbnail list is open - _onItemMotion(item) { - if (item === this._items[this._highlighted] || - item === this._items[this._delayedHighlighted]) - return Clutter.EVENT_PROPAGATE; - - const index = this._items.indexOf(item); - - if (this._mouseTimeOutId !== 0) { - GLib.source_remove(this._mouseTimeOutId); - this._delayedHighlighted = -1; - this._mouseTimeOutId = 0; - } - - if (this._altTabPopup.thumbnailsVisible) { - this._delayedHighlighted = index; - this._mouseTimeOutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - APP_ICON_HOVER_TIMEOUT, - () => { - this._enterItem(index); - this._delayedHighlighted = -1; - this._mouseTimeOutId = 0; - return GLib.SOURCE_REMOVE; - }); - GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem'); - } else { - this._itemEntered(index); - } - - return Clutter.EVENT_PROPAGATE; - } - - _enterItem(index) { - let [x, y] = global.get_pointer(); - let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); - if (this._items[index].contains(pickedActor)) - this._itemEntered(index); - } - - // We override SwitcherList's highlight() method to also deal with - // the AppSwitcher->ThumbnailSwitcher arrows. Apps with only 1 window - // will hide their arrows by default, but show them when their - // thumbnails are visible (ie, when the app icon is supposed to be - // in justOutline mode). Apps with multiple windows will normally - // show a dim arrow, but show a bright arrow when they are - // highlighted. - highlight(n, justOutline) { - if (this.icons[this._highlighted]) { - if (this.icons[this._highlighted].cachedWindows.length === 1) - this._arrows[this._highlighted].hide(); - else - this._arrows[this._highlighted].remove_style_pseudo_class('highlighted'); - } - - super.highlight(n, justOutline); - - if (this._highlighted !== -1) { - if (justOutline && this.icons[this._highlighted].cachedWindows.length === 1) - this._arrows[this._highlighted].show(); - else - this._arrows[this._highlighted].add_style_pseudo_class('highlighted'); - } - } - - _addIcon(appIcon) { - this.icons.push(appIcon); - let item = this.addItem(appIcon, appIcon.label); - - appIcon.app.connectObject('notify::state', app => { - if (app.state !== Shell.AppState.RUNNING) - this._removeIcon(app); - }, this); - - let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' }); - arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM)); - this.add_actor(arrow); - this._arrows.push(arrow); - - if (appIcon.cachedWindows.length === 1) - arrow.hide(); - else - item.add_accessible_state(Atk.StateType.EXPANDABLE); - } - - _removeIcon(item) { - const index = this.icons.findIndex(i => i === item); - if (index === -1) - return; - - this._arrows[index].destroy(); - this._arrows.splice(index, 1); - - this.icons.splice(index, 1); - this.removeItem(index); - } -}); - -/** - * Replace AltTab.AppIcon and insert this into the TilingAppSwitcher instead. - * This may contain multiple AppIcons to represent a tileGroup with chain icons - * between the AppIcons. - */ -const AppSwitcherItem = GObject.registerClass({ - Signals: { 'all-icons-removed': {} } -}, class AppSwitcherItem extends St.BoxLayout { - _init(windows) { - super._init({ vertical: false }); - - // A tiled window in a tileGroup of length 1, doesn't get a separate - // AppSwitcherItem. It gets added to the non-tiled windows' AppSwitcherItem - const tileGroup = windows[0].isTiled && Twm.getTileGroupFor(windows[0]); - this.isTileGroup = tileGroup && tileGroup.every(w => windows.includes(w)) && tileGroup?.length > 1; - this.cachedWindows = windows; - this.appIcons = []; - this.chainIcons = []; - - // Compatibility with AltTab.AppIcon - this.set_size = size => this.appIcons.forEach(i => i.set_size(size)); - this.label = null; - this.app = { - // Only raise the first window since we split up apps and tileGroups - activate_window: (window, timestamp) => { - Main.activateWindow(this.cachedWindows[0], timestamp); - }, - // Listening to the app-stop now happens in the custom _init func - // So prevent signal connection. here.. careful in case signal - // connection in the future is used for more... - connectObject: () => {} - }; - - this.updateAppIcons(); - } - - // Re/Create the AppIcons based on the cached window list - updateAppIcons() { - this.appIcons.forEach(i => i.destroy()); - this.appIcons = []; - this.chainIcons.forEach(i => i.destroy()); - this.chainIcons = []; - - const winTracker = Shell.WindowTracker.get_default(); - const path = Extension.lookupByURL(import.meta.url) - .dir.get_child('media/insert-link-symbolic.svg') - .get_path(); - const icon = new Gio.FileIcon({ file: Gio.File.new_for_path(path) }); - - const apps = this.isTileGroup - // All apps (even duplicates) - ? this.cachedWindows.map(w => winTracker.get_window_app(w)) - // Only unique apps - : this.cachedWindows.reduce((allApps, w) => { - const a = winTracker.get_window_app(w); - !allApps.includes(a) && allApps.push(a); - return allApps; - }, []); - - apps.forEach((app, idx) => { - // AppIcon - const appIcon = new AppIcon(app); - this.add_child(appIcon); - this.appIcons.push(appIcon); - - // Add chain to the right AppIcon except for the last AppIcon - if (idx >= apps.length - 1) - return; - - // Chain - const chain = new St.Icon({ - gicon: icon, - icon_size: 18 - }); - this.add_child(chain); - this.chainIcons.push(chain); - }); - - if (!this.appIcons.length) { - this.emit('all-icons-removed'); - return; - } - - this.label = this.appIcons[0].label; - } - - // Remove an AppIcon to the corresponding app. - // This doesn't update cached window list! - removeApp(app) { - for (let i = this.appIcons.length - 1; i >= 0; i--) { - const appIcon = this.appIcons[i]; - if (appIcon.app !== app) - continue; - - this.appIcons.splice(i, 1); - appIcon.destroy(); - const chain = this.chainIcons.splice(Math.max(0, i - 1), 1)[0]; - chain?.destroy(); - } - - if (!this.appIcons.length) - this.emit('all-icons-removed'); - } -}); - -const AppIcon = GObject.registerClass( -class AppIcon extends AltTab.AppIcon { - // Don't make the SwitcherButtons squares since 1 SwitcherButton - // may contain multiple AppIcons for a tileGroup. - vfunc_get_preferred_width() { - return this.get_preferred_height(-1); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js deleted file mode 100644 index f2c2fe1..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js +++ /dev/null @@ -1,553 +0,0 @@ -import { Clutter, Meta, Shell, St } from '../dependencies/gi.js'; -import { _, Main } from '../dependencies/shell.js'; - -import { Direction, DynamicKeybindings, Settings, Shortcuts } from '../common.js'; -import { Rect, Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -/** - * Class to handle the keyboard shortcuts (on the extension side) except the - * ones related to the Layouts. For those, see layoutsManager.js. - */ - -export default class TilingKeybindingHandler { - constructor() { - const allowInOverview = [Shortcuts.TOGGLE_POPUP]; - this._keyBindings = Shortcuts.getAllKeys(); - this._keyBindings.forEach(key => { - Main.wm.addKeybinding( - key, - Settings.getGioObject(), - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL | (allowInOverview.includes(key) && Shell.ActionMode.OVERVIEW), - this._onCustomKeybindingPressed.bind(this, key) - ); - }); - } - - destroy() { - this._keyBindings.forEach(key => Main.wm.removeKeybinding(key)); - this._debuggingIndicators?.forEach(i => i.destroy()); - } - - /** - * @param {string} shortcutName - */ - async _onCustomKeybindingPressed(shortcutName) { - // Debugging - const debugging = [Shortcuts.DEBUGGING, Shortcuts.DEBUGGING_FREE_RECTS]; - if (debugging.includes(shortcutName)) { - if (this._debuggingIndicators) { - this._debuggingIndicators.forEach(i => i.destroy()); - this._debuggingIndicators = null; - } else { - const createIndicators = shortcutName === Shortcuts.DEBUGGING - ? Util.___debugShowTiledRects - : Util.___debugShowFreeScreenRects; - this._debuggingIndicators = await createIndicators.call(Util); - } - return; - - // Toggle the Tiling Popup - } else if (shortcutName === Shortcuts.TOGGLE_POPUP) { - const toggleTo = !Settings.getBoolean(Settings.ENABLE_TILING_POPUP); - Settings.setBoolean(Settings.ENABLE_TILING_POPUP, toggleTo); - Main.notify('Tiling Assistant', toggleTo - ? _('Tiling popup enabled') - : _('Tiling popup was disabled')); - return; - } - - const window = global.display.focus_window; - if (!window) - return; - - // Auto-tile: tile to empty space. If there's none: untile, - // if it's already tiled else maximize - if (shortcutName === Shortcuts.AUTO_FILL) { - if (Twm.isMaximized(window)) { - Twm.untile(window); - } else { - const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: !window.isTiled }); - const tRects = topTileGroup.map(w => w.tiledRect); - const tileRect = Twm.getBestFreeRect(tRects, { currRect: window.tiledRect }); - Twm.toggleTiling(window, tileRect); - } - - // Tile Editing Mode - } else if (shortcutName === Shortcuts.EDIT_MODE) { - const TileEditingMode = await import('./tileEditingMode.js'); - const tileEditor = new TileEditingMode.TileEditor(); - tileEditor.open(); - - // Toggle always-on-top - } else if (shortcutName === Shortcuts.ALWAYS_ON_TOP) { - window.is_above() ? window.unmake_above() : window.make_above(); - - // Toggle maximization vertically - } else if (shortcutName === Shortcuts.MAXIMIZE_V) { - const workArea = new Rect(window.get_work_area_current_monitor()); - const currRect = window.tiledRect ?? window.get_frame_rect(); - - // Is tiled or maximized with this extension - if (window.untiledRect && currRect.height === workArea.height) { - // Is maximized - if (currRect.width === workArea.width) { - const tileRect = new Rect(workArea.x, window.untiledRect.y, workArea.width, window.untiledRect.height); - Twm.tile(window, tileRect); - // Is tiled - } else { - Twm.untile(window); - } - - // Maximize vertically even if the height may already be equal to the workArea - // e. g. via double-click titlebar, maximize-window-button or whatever - } else { - const tileRect = new Rect(currRect.x, workArea.y, currRect.width, workArea.height); - Twm.tile(window, tileRect); - } - - // Toggle maximization horizontally - } else if (shortcutName === Shortcuts.MAXIMIZE_H) { - const workArea = new Rect(window.get_work_area_current_monitor()); - const currRect = window.tiledRect ?? window.get_frame_rect(); - - // Is tiled or maximized with this extension - if (window.untiledRect && currRect.width === workArea.width) { - // Is maximized - if (currRect.height === workArea.height) { - const tileRect = new Rect(window.untiledRect.x, workArea.y, window.untiledRect.width, workArea.height); - Twm.tile(window, tileRect); - // Is tiled - } else { - Twm.untile(window); - } - - // Maximize horizontally even if the width may already be equal to the workArea - // e. g. via double-click titlebar, maximize-window-button or whatever - } else { - const tileRect = new Rect(workArea.x, currRect.y, workArea.width, currRect.height); - Twm.tile(window, tileRect); - } - - // Restore window size - } else if (shortcutName === Shortcuts.RESTORE_WINDOW) { - if (window.untiledRect) // Tiled & maximized with gaps - Twm.untile(window, { clampToWorkspace: true }); - else if (window.get_maximized()) - window.unmaximize(window.get_maximized()); - - // Center window - } else if (shortcutName === Shortcuts.CENTER_WINDOW) { - const workArea = new Rect(window.get_work_area_current_monitor()); - if (window.isTiled) { - const currRect = window.tiledRect; - const tileRect = new Rect( - workArea.center.x - Math.floor(currRect.width / 2), - workArea.center.y - Math.floor(currRect.height / 2), - currRect.width, - currRect.height - ); - - if (tileRect.equal(currRect)) - return; - - Twm.tile(window, tileRect, { openTilingPopup: false }); - } else if (!Twm.isMaximized(window)) { - if (!window.allows_move()) - return; - - const currRect = window.get_frame_rect(); - const x = workArea.center.x - Math.floor(currRect.width / 2); - const y = workArea.center.y - Math.floor(currRect.height / 2); - - if (x === currRect.x && y === currRect.y) - return; - - const wActor = window.get_compositor_private(); - wActor && Main.wm._prepareAnimationInfo( - global.window_manager, - wActor, - currRect, - Meta.SizeChange.UNMAXIMIZE - ); - window.move_frame(false, x, y); - } - // Tile a window but ignore T-A features - } else if ([Shortcuts.TOP_IGNORE_TA, Shortcuts.BOTTOM_IGNORE_TA, - Shortcuts.LEFT_IGNORE_TA, Shortcuts.RIGHT_IGNORE_TA, - Shortcuts.TOP_LEFT_IGNORE_TA, Shortcuts.TOP_RIGHT_IGNORE_TA, - Shortcuts.BOTTOM_LEFT_IGNORE_TA, - Shortcuts.BOTTOM_RIGHT_IGNORE_TA].includes(shortcutName) - ) { - const workArea = new Rect(window.get_work_area_current_monitor()); - const rect = Twm.getDefaultTileFor(shortcutName, workArea); - Twm.toggleTiling(window, rect, { ignoreTA: true }); - // Tile a window - } else { - const dynamicBehavior = Settings.DYNAMIC_KEYBINDINGS; - const dynamicSetting = Settings.getInt(dynamicBehavior); - const windowsStyle = DynamicKeybindings.TILING_STATE_WINDOWS; - const isWindowsStyle = dynamicSetting === windowsStyle; - const workArea = new Rect(window.get_work_area_current_monitor()); - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - - switch (dynamicSetting) { - case DynamicKeybindings.FOCUS: - this._dynamicFocus(window, shortcutName); - break; - case DynamicKeybindings.TILING_STATE: - case DynamicKeybindings.TILING_STATE_WINDOWS: - this._dynamicTilingState(window, shortcutName, isWindowsStyle); - break; - case DynamicKeybindings.FAVORITE_LAYOUT: - this._dynamicFavoriteLayout(window, shortcutName); - break; - default: - Twm.toggleTiling(window, rect); - } - } - } - - /** - * Tiles or moves the focus depending on the `windows` tiling state. - * - * @param {Meta.Window} window a Meta.Window as the starting position. - * @param {string} shortcutName indicates the direction we tile or move - * the focus to. - */ - _dynamicFocus(window, shortcutName) { - const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); - const workArea = new Rect(window.get_work_area_current_monitor()); - - // Toggle tile state of the window, if it isn't tiled - // or if it is the only window which is. - if (!window.isTiled || topTileGroup.length === 1) { - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - } - - let direction; - switch (shortcutName) { - case Shortcuts.MAXIMIZE: - case Shortcuts.TOP: - direction = Direction.N; - break; - case Shortcuts.BOTTOM: - direction = Direction.S; - break; - case Shortcuts.LEFT: - direction = Direction.W; - break; - case Shortcuts.RIGHT: - direction = Direction.E; - } - - const nearestWindow = Twm.getNearestWindow( - window, - topTileGroup, - direction, - false - ); - - if (!nearestWindow) { - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - } - - // Activate() caused problems with an extensions' prefs window, if the - // extensions-app wasn't open. - nearestWindow.focus(global.get_current_time()); - - // Animation for visibility with a tmp 'tile preview' - const fromRect = window.get_frame_rect(); - const focusIndicator = new St.Widget({ - style_class: 'tile-preview', - opacity: 0, - x: fromRect.x, - y: fromRect.y, - width: fromRect.width, - height: fromRect.height - }); - Main.uiGroup.add_child(focusIndicator); - const toRect = nearestWindow.get_frame_rect(); - focusIndicator.ease({ - opacity: 255, - x: toRect.x, - y: toRect.y, - width: toRect.width, - height: toRect.height, - duration: 200, - mode: Clutter.AnimationMode.EASE_OUT_QUART, - onComplete: () => { - focusIndicator.ease({ - opacity: 0, - duration: 200, - mode: Clutter.AnimationMode.EASE_IN_OUT_CIRC, - delay: 100, - onComplete: () => focusIndicator.destroy() - }); - } - }); - } - - /** - * Changes the tiling state of the `window` based on its current tiling - * state and the activated shortcut. - * - * @param {Meta.Window} window a Meta.Window. - * @param {string} shortcutName the shortcut. - * @param {boolean} isWindowsStyle minimize when the `window` isn't tiled or - * if it's tiled to the bottom and the 'tile to bottom' shortcut is - * activated. - */ - _dynamicTilingState(window, shortcutName, isWindowsStyle) { - const workArea = new Rect(window.get_work_area_current_monitor()); - - if (Twm.isMaximized(window)) { - switch (shortcutName) { - case Shortcuts.MAXIMIZE: - case Shortcuts.TOP: { - const rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); - Twm.tile(window, rect, { skipAnim: true }); - break; - } case Shortcuts.BOTTOM: { - Twm.untile(window); - break; - } default: { - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - } - } - - return; - } else if (!window.isTiled) { - switch (shortcutName) { - case Shortcuts.BOTTOM: { - if (isWindowsStyle) { - window.minimize(); - break; - } - // falls through - } default: { - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - } - } - - return; - } - - const wRect = window.tiledRect; - const isLeftHalf = - wRect.x === workArea.x && - wRect.y === workArea.y && - wRect.width !== workArea.width && - wRect.height === workArea.height; - const isRightHalf = - wRect.x !== workArea.x && - wRect.y === workArea.y && - wRect.x2 === workArea.x2 && - wRect.height === workArea.height; - const isTopHalf = - wRect.x === workArea.x && - wRect.y === workArea.y && - wRect.width === workArea.width && - wRect.height !== workArea.height; - const isBottomHalf = - wRect.x === workArea.x && - wRect.y !== workArea.y && - wRect.width === workArea.width && - wRect.y2 === workArea.y2; - const isTopLeftQuarter = - wRect.x === workArea.x && - wRect.y === workArea.y && - wRect.width !== workArea.width && - wRect.height !== workArea.height; - const isTopRightQuarter = - wRect.x !== workArea.x && - wRect.y === workArea.y && - wRect.x2 === workArea.x2 && - wRect.height !== workArea.height; - const isBottomLeftQuarter = - wRect.x === workArea.x && - wRect.y !== workArea.y && - wRect.width !== workArea.width && - wRect.y2 === workArea.y2; - const isBottomRightQuarter = - wRect.x !== workArea.x && - wRect.y !== workArea.y && - wRect.x2 === workArea.x2 && - wRect.y2 === workArea.y2; - - let rect; - if (isLeftHalf) { - switch (shortcutName) { - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - rect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.RIGHT: - Twm.untile(window); - return; - } - } else if (isRightHalf) { - switch (shortcutName) { - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - rect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.LEFT: - Twm.untile(window); - return; - } - } else if (isTopHalf) { - switch (shortcutName) { - case Shortcuts.TOP: - rect = Twm.getTileFor(Shortcuts.MAXIMIZE, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.LEFT: - rect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.RIGHT: - rect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - Twm.untile(window); - return; - } - } else if (isBottomHalf) { - switch (shortcutName) { - case Shortcuts.LEFT: - rect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.RIGHT: - rect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - Twm.untile(window); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); - isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); - return; - } - } else if (isTopLeftQuarter) { - switch (shortcutName) { - case Shortcuts.RIGHT: - rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - } - } else if (isTopRightQuarter) { - switch (shortcutName) { - case Shortcuts.LEFT: - rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - } - } else if (isBottomLeftQuarter) { - switch (shortcutName) { - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - rect = Twm.getTileFor(Shortcuts.LEFT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.RIGHT: - rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); - isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); - return; - } - } else if (isBottomRightQuarter) { - switch (shortcutName) { - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - rect = Twm.getTileFor(Shortcuts.RIGHT, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.LEFT: - rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - return; - case Shortcuts.BOTTOM: - rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); - isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); - return; - } - } - - Twm.toggleTiling(window, Twm.getTileFor(shortcutName, workArea, window.get_monitor())); - } - - _dynamicFavoriteLayout(window, shortcutName) { - const workArea = new Rect(window.get_work_area_current_monitor()); - const toggleTiling = () => { - const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); - Twm.toggleTiling(window, rect); - }; - - if (!window.isTiled) { - toggleTiling(); - return; - } - - const favoriteLayout = Util.getFavoriteLayout(window.get_monitor()); - if (favoriteLayout.length <= 1) { - toggleTiling(); - return; - } - - let direction; - switch (shortcutName) { - case Shortcuts.TOP: - case Shortcuts.MAXIMIZE: - direction = Direction.N; - break; - case Shortcuts.BOTTOM: - direction = Direction.S; - break; - case Shortcuts.LEFT: - direction = Direction.W; - break; - case Shortcuts.RIGHT: - direction = Direction.E; - } - - if (direction) { - const neighbor = window.tiledRect.getNeighbor(direction, favoriteLayout); - Twm.tile(window, neighbor, { openTilingPopup: false }); - } else { - toggleTiling(); - } - } -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/layoutsManager.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/layoutsManager.js deleted file mode 100644 index 7722980..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/layoutsManager.js +++ /dev/null @@ -1,559 +0,0 @@ -import { Clutter, Gio, GObject, Meta, Shell, St } from '../dependencies/gi.js'; -import { - _, - Extension, - Main, - PanelMenu, - PopupMenu -} from '../dependencies/shell.js'; - -import { Layout, Settings } from '../common.js'; -import { Rect, Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -/** - * Here are the classes to handle PopupLayouts on the shell / extension side. - * See src/prefs/layoutsPrefs.js for more details and general info about layouts. - * In summary, a Layout is an array of LayoutItems. A LayoutItem is a JS Object - * and has a rect, an appId and a loopType. Only the rect is mandatory. AppId may - * be null or a String. Same for the LoopType. If a layout is activated, we will - * loop / step through each LayoutItem and spawn a Tiling Popup one after the - * other for the rects and offer to tile a window to that rect. If an appId is - * defined, instead of calling the Tiling Popup, we tile (a new Instance of) - * the app to the rect. If a LoopType is defined, instead of going to the next - * item / rect, we spawn a Tiling Popup on the same item / rect and all the - * tiled windows will share that spot evenly (a la 'Master and Stack'). - * - * Additionally, there the user can select a 'favorite' layout among the - * PopupLayouts. That layout will then be used as an fixed alternative mode to - * the Edge Tiling. - */ - -export default class TilingLayoutsManager { - constructor() { - // this._items is an array of LayoutItems (see explanation above). - // this._currItem is 1 LayoutItem. A LayoutItem's rect only hold ratios - // from 0 - 1. this._currRect is a Rect scaled to the workArea. - this._items = []; - this._currItem = null; - this._currRect = null; - - // Preview to show where the window will tile to, similar - // to the tile preview when dnding to the screen edges - this._rectPreview = null; - - // Keep track of the windows which were already tiled with the current - // layout and the remaining windows. Special-case windows, which were tiled - // within a loop since they need to be re-adjusted for each new window - // tiled to the same spot. The looped array is cleared after each 'step' / - // LayoutItem change. - this._tiledWithLayout = []; - this._tiledWithLoop = []; - this._remainingWindows = []; - - // Bind the keyboard shortcuts for each layout and the layout searchers - this._keyBindings = []; - - for (let i = 0; i < 20; i++) { - this._keyBindings.push(`activate-layout${i}`); - Main.wm.addKeybinding( - `activate-layout${i}`, - Settings.getGioObject(), - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL, - this.startLayouting.bind(this, i) - ); - } - - this._keyBindings.push('search-popup-layout'); - Main.wm.addKeybinding( - 'search-popup-layout', - Settings.getGioObject(), - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL, - this.openPopupSearch.bind(this) - ); - - // Add panel indicator - this._panelIndicator = new PanelIndicator(); - Main.panel.addToStatusArea( - 'tiling-assistant@leleat-on-github', - this._panelIndicator); - this._settingsId = Settings.changed(Settings.SHOW_LAYOUT_INDICATOR, () => { - this._panelIndicator.visible = Settings.getBoolean(Settings.SHOW_LAYOUT_INDICATOR); - }); - this._panelIndicator.visible = Settings.getBoolean(Settings.SHOW_LAYOUT_INDICATOR); - this._panelIndicator.connect('layout-activated', (src, idx) => this.startLayouting(idx)); - } - - destroy() { - Settings.disconnect(this._settingsId); - this._finishLayouting(); - this._keyBindings.forEach(key => Main.wm.removeKeybinding(key)); - this._panelIndicator.destroy(); - this._panelIndicator = null; - } - - /** - * Opens a popup window so the user can activate a layout by name - * instead of the keyboard shortcut. - */ - openPopupSearch() { - const layouts = Util.getLayouts(); - if (!layouts.length) { - Main.notify('Tiling Assistant', _('No valid layouts defined.')); - return; - } - - const search = new LayoutSearch(layouts); - search.connect('item-activated', (s, index) => this.startLayouting(index)); - } - - /** - * Starts tiling to a Popup Layout. - * - * @param {number} index the index of the layout we start tiling to. - */ - startLayouting(index) { - const layout = Util.getLayouts()?.[index]; - if (!layout) - return; - - const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); - this._remainingWindows = Twm.getWindows(allWs); - this._items = new Layout(layout).getItems(); - this._currItem = null; - - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = global.display.get_current_monitor(); - const workArea = activeWs.get_work_area_for_monitor(monitor); - this._rectPreview?.destroy(); - this._rectPreview = new St.Widget({ - style_class: 'tile-preview', - opacity: 0, - x: workArea.x + workArea.width / 2, - y: workArea.y + workArea.height / 2 - }); - Main.layoutManager.addChrome(this._rectPreview); - - this._step(); - } - - _finishLayouting() { - this._items = []; - this._currItem = null; - this._currRect = null; - - this._rectPreview?.destroy(); - this._rectPreview = null; - - this._tiledWithLayout = []; - this._tiledWithLoop = []; - this._remainingWindows = []; - } - - _step(loopType = null) { - // If we aren't looping on the current item, we need to prepare for the - // step by getting the next item / rect. If we are looping, we stay on - // the current item / rect and open a new Tiling Popup for that rect. - if (!loopType) { - // We're at the last item and not looping, so there are no more items. - if (this._currItem === this._items.at(-1)) { - this._finishLayouting(); - return; - } - - const currIdx = this._items.indexOf(this._currItem); - this._currItem = this._items[currIdx + 1]; - - // Scale the item's rect to the workArea - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = global.display.get_current_monitor(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - const rectRatios = this._currItem.rect; - this._currRect = new Rect( - workArea.x + Math.floor(rectRatios.x * workArea.width), - workArea.y + Math.floor(rectRatios.y * workArea.height), - Math.ceil(rectRatios.width * workArea.width), - Math.ceil(rectRatios.height * workArea.height) - ); - - // Try to compensate possible rounding errors when scaling up the - // rect by aligning it with the rects, which were already tiled - // using this layout and the workArea. - this._tiledWithLayout.forEach(w => this._currRect.tryAlignWith(w.tiledRect)); - this._currRect.tryAlignWith(workArea); - } - - const appId = this._currItem.appId; - appId ? this._openAppTiled(appId) : this._openTilingPopup(); - } - - _openAppTiled(appId) { - const app = Shell.AppSystem.get_default().lookup_app(appId); - if (!app) { - Main.notify('Tiling Assistant', _('Popup Layouts: App not found.')); - this._finishLayouting(); - return; - } - - const winTracker = Shell.WindowTracker.get_default(); - const idx = this._remainingWindows.findIndex(w => winTracker.get_window_app(w) === app); - const window = this._remainingWindows[idx]; - idx !== -1 && this._remainingWindows.splice(idx, 1); - - if (window) - Twm.tile(window, this._currRect, { openTilingPopup: false }); - else if (app.can_open_new_window()) - Twm.openAppTiled(app, this._currRect); - - this._step(); - } - - async _openTilingPopup() { - // There are no open windows left to tile using the Tiling Popup. - // However there may be items with appIds, which we want to open. - // So continue... - if (!this._remainingWindows.length) { - this._step(); - return; - } - - // Animate the rect preview - this._rectPreview.ease({ - x: this._currRect.x, - y: this._currRect.y, - width: this._currRect.width, - height: this._currRect.height, - opacity: 255, - duration: 200, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }); - - // Create the Tiling Popup - const TilingPopup = await import('./tilingPopup.js'); - const popup = new TilingPopup.TilingSwitcherPopup( - this._remainingWindows, - this._currRect, - // If this._currItem is the last item and we don't loop over it, - // allow the Tiling Popup itself to spawn another instance of - // a Tiling Popup, if there is free screen space. - this._currItem === this._items.at(-1) && !this._currItem.loopType - ); - const stacked = global.display.sort_windows_by_stacking(this._tiledWithLayout); - const tileGroup = stacked.reverse(); - if (!popup.show(tileGroup)) { - popup.destroy(); - this._finishLayouting(); - return; - } - - popup.connect('closed', this._onTilingPopupClosed.bind(this)); - } - - _onTilingPopupClosed(tilingPopup, canceled) { - if (canceled) { - if (this._currItem.loopType) { - this._tiledWithLoop = []; - this._step(); - } else { - this._finishLayouting(); - } - } else { - const tiledWindow = tilingPopup.tiledWindow; - this._tiledWithLayout.push(tiledWindow); - const i = this._remainingWindows.indexOf(tiledWindow); - this._remainingWindows.splice(i, 1); - - // Make all windows, which were tiled during the current loop, - // share the current rect evenly -> like the 'Stack' part of a - // 'Master and Stack' - if (this._currItem.loopType) { - this._tiledWithLoop.push(tiledWindow); - this._tiledWithLoop.forEach((w, idx) => { - const rect = this._currRect.copy(); - const [pos, dimension] = this._currItem.loopType === 'h' - ? ['y', 'height'] - : ['x', 'width']; - rect[dimension] /= this._tiledWithLoop.length; - rect[pos] += idx * rect[dimension]; - Twm.tile(w, rect, { openTilingPopup: false, skipAnim: true }); - }); - } - - this._step(this._currItem.loopType); - } - } -} - -/** - * The GUI class for the Layout search. - */ -const LayoutSearch = GObject.registerClass({ - Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] } } -}, class TilingLayoutsSearch extends St.Widget { - _init(layouts) { - const activeWs = global.workspace_manager.get_active_workspace(); - super._init({ - reactive: true, - x: Main.uiGroup.x, - y: Main.uiGroup.y, - width: Main.uiGroup.width, - height: Main.uiGroup.height - }); - Main.uiGroup.add_child(this); - - const grab = Main.pushModal(this); - // We expect at least a keyboard grab here - if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { - Main.popModal(grab); - return false; - } - - this._grab = grab; - this._haveModal = true; - this._focused = -1; - this._items = []; - - this.connect('button-press-event', () => this.destroy()); - - const popup = new St.BoxLayout({ - style_class: 'switcher-list', - vertical: true, - width: 500 - }); - this.add_child(popup); - - const fontSize = 16; - const entry = new St.Entry({ - style: `font-size: ${fontSize}px;\ - border-radius: 16px; - margin-bottom: 12px;`, - // The cursor overlaps the text, so add some spaces at the beginning - hint_text: ` ${_('Type to search...')}` - }); - const entryClutterText = entry.get_clutter_text(); - entryClutterText.connect('key-press-event', this._onKeyPressed.bind(this)); - entryClutterText.connect('text-changed', this._onTextChanged.bind(this)); - popup.add_child(entry); - - this._items = layouts.map(layout => { - const item = new SearchItem(layout._name, fontSize); - item.connect('button-press-event', this._onItemClicked.bind(this)); - popup.add_child(item); - return item; - }); - - if (!this._items.length) { - this.destroy(); - return; - } - - const monitor = global.display.get_current_monitor(); - const workArea = activeWs.get_work_area_for_monitor(monitor); - popup.set_position(workArea.x + workArea.width / 2 - popup.width / 2, - workArea.y + workArea.height / 2 - popup.height / 2); - - entry.grab_key_focus(); - this._focus(0); - } - - destroy() { - if (this._haveModal) { - Main.popModal(this._grab); - this._haveModal = false; - } - - super.destroy(); - } - - _onKeyPressed(clutterText, event) { - const keySym = event.get_key_symbol(); - if (keySym === Clutter.KEY_Escape) { - this.destroy(); - return Clutter.EVENT_STOP; - } else if (keySym === Clutter.KEY_Return || - keySym === Clutter.KEY_KP_Enter || - keySym === Clutter.KEY_ISO_Enter) { - this._activate(); - return Clutter.EVENT_STOP; - } else if (keySym === Clutter.KEY_Down) { - this._focusNext(); - return Clutter.EVENT_STOP; - } else if (keySym === Clutter.KEY_Up) { - this._focusPrev(); - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } - - _onTextChanged(clutterText) { - const filterText = clutterText.get_text(); - this._items.forEach(item => { - item.text.toLowerCase().includes(filterText.toLowerCase()) - ? item.show() - : item.hide(); - }); - const nextVisibleIdx = this._items.findIndex(item => item.visible); - this._focus(nextVisibleIdx); - } - - _onItemClicked(item) { - this._focused = this._items.indexOf(item); - this._activate(); - } - - _focusPrev() { - this._focus((this._focused + this._items.length - 1) % this._items.length); - } - - _focusNext() { - this._focus((this._focused + 1) % this._items.length); - } - - _focus(newIdx) { - const prevItem = this._items[this._focused]; - const newItem = this._items[newIdx]; - this._focused = newIdx; - - prevItem?.remove_style_class_name('tiling-layout-search-highlight'); - newItem?.add_style_class_name('tiling-layout-search-highlight'); - } - - _activate() { - this._focused !== -1 && this.emit('item-activated', this._focused); - this.destroy(); - } -}); - -/** - * An Item representing a Layout within the Popup Layout search. - */ -const SearchItem = GObject.registerClass( -class TilingLayoutsSearchItem extends St.Label { - _init(text, fontSize) { - super._init({ - // Add some spaces to the beginning to align it better - // with the rounded corners - text: ` ${text || _('Nameless layout...')}`, - style: `font-size: ${fontSize}px;\ - text-align: left;\ - padding: 8px\ - margin-bottom: 2px`, - reactive: true - }); - } -}); - -/** - * A panel indicator to activate and favoritize a layout. - */ -const PanelIndicator = GObject.registerClass({ - Signals: { 'layout-activated': { param_types: [GObject.TYPE_INT] } } -}, class PanelIndicator extends PanelMenu.Button { - _init() { - super._init(0.0, 'Layout Indicator (Tiling Assistant)'); - - const path = Extension.lookupByURL(import.meta.url) - .dir - .get_child('media/preferences-desktop-apps-symbolic.svg') - .get_path(); - const gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(path) }); - this.add_child(new St.Icon({ - gicon, - style_class: 'system-status-icon' - })); - - const menuAlignment = 0.0; - this.setMenu(new PopupMenu.PopupMenu(this, menuAlignment, St.Side.TOP)); - } - - vfunc_event(event) { - if (this.menu && - (event.type() === Clutter.EventType.TOUCH_BEGIN || - event.type() === Clutter.EventType.BUTTON_PRESS) - ) { - this._updateItems(); - this.menu.toggle(); - } - - return Clutter.EVENT_PROPAGATE; - } - - _updateItems() { - this.menu.removeAll(); - - const layouts = Util.getLayouts(); - if (!layouts.length) { - const item = new PopupMenu.PopupMenuItem(_('No valid layouts defined.')); - item.setSensitive(false); - this.menu.addMenuItem(item); - } else { - // Update favorites with monitor count and fill with '-1', if necessary - const tmp = Settings.getStrv(Settings.FAVORITE_LAYOUTS); - const count = Math.max(Main.layoutManager.monitors.length, tmp.length); - const favorites = [...new Array(count)].map((m, monitorIndex) => { - return tmp[monitorIndex] ?? '-1'; - }); - Settings.setStrv(Settings.FAVORITE_LAYOUTS, favorites); - - // Create popup menu items - layouts.forEach((layout, idx) => { - const name = layout._name || `Layout ${idx + 1}`; - const item = new PopupFavoriteMenuItem(name, idx); - item.connect('activate', () => { - Main.overview.hide(); - this.emit('layout-activated', idx); - }); - item.connect('favorite-changed', this._updateItems.bind(this)); - this.menu.addMenuItem(item); - }); - } - - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - const settingsButton = new PopupMenu.PopupImageMenuItem('Preferences', 'emblem-system-symbolic'); - // Center button without changing the size (for the hover highlight) - settingsButton._icon.set_x_expand(true); - settingsButton.label.set_x_expand(true); - settingsButton.connect('activate', - () => Extension.lookupByURL(import.meta.url).openPreferences()); - this.menu.addMenuItem(settingsButton); - } -}); - -/** - * A PopupMenuItem for the PopupMenu of the PanelIndicator. - */ -const PopupFavoriteMenuItem = GObject.registerClass({ - Signals: { 'favorite-changed': { param_types: [GObject.TYPE_INT] } } -}, class PopupFavoriteMenuItem extends PopupMenu.PopupBaseMenuItem { - _init(text, layoutIndex) { - super._init(); - - this.add_child(new St.Label({ - text, - x_expand: true - })); - - const favorites = Settings.getStrv(Settings.FAVORITE_LAYOUTS); - Main.layoutManager.monitors.forEach((m, monitorIndex) => { - const favoriteButton = new St.Button({ - child: new St.Icon({ - icon_name: favorites[monitorIndex] === `${layoutIndex}` ? 'starred-symbolic' : 'non-starred-symbolic', - style_class: 'popup-menu-icon' - }) - }); - this.add_child(favoriteButton); - - // Update gSetting with new Favorite (act as a toggle button) - favoriteButton.connect('clicked', () => { - const currFavorites = Settings.getStrv(Settings.FAVORITE_LAYOUTS); - currFavorites[monitorIndex] = currFavorites[monitorIndex] === `${layoutIndex}` ? '-1' : `${layoutIndex}`; - Settings.setStrv(Settings.FAVORITE_LAYOUTS, currFavorites); - this.emit('favorite-changed', monitorIndex); - }); - }); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/moveHandler.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/moveHandler.js deleted file mode 100644 index 43d3c96..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/moveHandler.js +++ /dev/null @@ -1,902 +0,0 @@ -import { Clutter, GLib, GObject, Gio, Meta, Mtk } from '../dependencies/gi.js'; -import { Main, WindowManager } from '../dependencies/shell.js'; -import { WINDOW_ANIMATION_TIME } from '../dependencies/unexported/windowManager.js'; - -import { Orientation, RestoreOn, MoveModes, Settings, Shortcuts } from '../common.js'; -import { Rect, Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -/** - * This class gets to handle the move events (grab & monitor change) of windows. - * If the moved window is tiled at the start of the grab, untile it. This is - * done by releasing the grab via code, resizing the window, and then restarting - * the grab via code. On Wayland this may not be reliable. As a workaround there - * is a setting to restore a tiled window's size on the actual grab end. - */ - -export default class TilingMoveHandler { - constructor() { - const moveOps = [Meta.GrabOp.MOVING, Meta.GrabOp.KEYBOARD_MOVING]; - - this._displaySignals = []; - const g1Id = global.display.connect('grab-op-begin', (src, window, grabOp) => { - grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED - - if (window && moveOps.includes(grabOp)) - this._onMoveStarted(window, grabOp); - }); - this._displaySignals.push(g1Id); - - const wId = global.display.connect('window-entered-monitor', this._onMonitorEntered.bind(this)); - this._displaySignals.push(wId); - - // Save the windows, which need to make space for the - // grabbed window (this is for the so called 'adaptive mode'): - // { window1: newTileRect1, window2: newTileRect2, ... } - this._splitRects = new Map(); - // The rect the grabbed window will tile to - // (it may differ from the tilePreview's rect) - this._tileRect = null; - - this._favoritePreviews = []; - this._tilePreview = new TilePreview(); - - // The mouse button mod to move/resize a window may be changed to Alt. - // So switch Alt and Super in our own prefs, if the user switched from - // Super to Alt. - const wmPrefs = new Gio.Settings({ - schema_id: 'org.gnome.desktop.wm.preferences' - }); - const altAsMod = wmPrefs.get_string('mouse-button-modifier') === ''; - if (altAsMod) { - for (const s of [Settings.ADAPTIVE_TILING_MOD, Settings.FAVORITE_LAYOUT_MOD]) { - const mod = Settings.getInt(s); - if (mod === 1) // 1 -> Alt; see settings ui - Settings.setInt(s, 3); // 3 -> Super; see settings ui - } - } - } - - destroy() { - this._displaySignals.forEach(sId => global.display.disconnect(sId)); - this._tilePreview.destroy(); - - if (this._latestMonitorLockTimerId) { - GLib.Source.remove(this._latestMonitorLockTimerId); - this._latestMonitorLockTimerId = null; - } - - if (this._latestPreviewTimerId) { - GLib.Source.remove(this._latestPreviewTimerId); - this._latestPreviewTimerId = null; - } - - if (this._cursorChangeTimerId) { - GLib.Source.remove(this._cursorChangeTimerId); - this._cursorChangeTimerId = null; - } - - if (this._restoreSizeTimerId) { - GLib.Source.remove(this._restoreSizeTimerId); - this._restoreSizeTimerId = null; - } - - if (this._movingTimerId) { - GLib.Source.remove(this._movingTimerId); - this._movingTimerId = null; - } - } - - _onMonitorEntered(src, monitorNr, window) { - if (this._isGrabOp) - // Reset preview mode: - // Currently only needed to grab the favorite layout for the new monitor. - this._preparePreviewModeChange(this._currPreviewMode, window); - } - - _onMoveStarted(window, grabOp) { - // Also work with a window, which was maximized by GNOME natively - // because it may have been tiled with this extension before being - // maximized so we need to restore its size to pre-tiling. - this._wasMaximizedOnStart = window.get_maximized(); - const [x, y] = global.get_pointer(); - - // Try to restore the window size - const restoreSetting = Settings.getInt(Settings.RESTORE_SIZE_ON); - if ((window.tiledRect || this._wasMaximizedOnStart) && - restoreSetting === RestoreOn.ON_GRAB_START - ) { - // HACK: - // The grab begin signal (and thus this function call) gets fired - // at the moment of the first click. However I don't want to restore - // the window size on just a click. Only if the user actually wanted - // to start a grab i.e. if the click is held for a bit or if the - // cursor moved while holding the click. I assume a cursor change - // means the grab was released since I couldn't find a better way... - let grabReleased = false; - let cursorId = global.display.connect('cursor-updated', () => { - grabReleased = true; - cursorId && global.display.disconnect(cursorId); - cursorId = 0; - }); - // Clean up in case my assumption mentioned above is wrong - // and the cursor never gets updated or something else... - this._cursorChangeTimerId && GLib.Source.remove(this._cursorChangeTimerId); - this._cursorChangeTimerId = GLib.timeout_add(GLib.PRIORITY_LOW, 400, () => { - cursorId && global.display.disconnect(cursorId); - cursorId = 0; - this._cursorChangeTimerId = null; - return GLib.SOURCE_REMOVE; - }); - - let counter = 0; - this._restoreSizeTimerId && GLib.Source.remove(this._restoreSizeTimerId); - this._restoreSizeTimerId = GLib.timeout_add(GLib.PRIORITY_HIGH_IDLE, 10, () => { - if (grabReleased) { - this._restoreSizeTimerId = null; - return GLib.SOURCE_REMOVE; - } - - counter += 10; - if (counter >= 400) { - this._restoreSizeAndRestartGrab(window, x, y, grabOp); - this._restoreSizeTimerId = null; - return GLib.SOURCE_REMOVE; - } - - const [currX, currY] = global.get_pointer(); - const currPoint = { x: currX, y: currY }; - const oldPoint = { x, y }; - const moveDist = Util.getDistance(currPoint, oldPoint); - if (moveDist > 10) { - this._restoreSizeAndRestartGrab(window, x, y, grabOp); - this._restoreSizeTimerId = null; - return GLib.SOURCE_REMOVE; - } - - return GLib.SOURCE_CONTINUE; - }); - - // Tile preview - } else { - this._isGrabOp = true; - this._monitorNr = global.display.get_current_monitor(); - this._lastMonitorNr = this._monitorNr; - this._lastPointerPos = { x, y }; - this._pointerDidntMove = false; - this._movingTimerDuration = 20; - this._movingTimeoutsSinceUpdate = 0; - this._topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); - - // When low performance mode is enabled we use a timer to periodically - // update the tile previews so that we don't update the tile preview - // as often when compared to the position-changed signal. - if (Settings.getBoolean(Settings.LOW_PERFORMANCE_MOVE_MODE)) { - this._movingTimerId = GLib.timeout_add( - GLib.PRIORITY_IDLE, - this._movingTimerDuration, - this._onMoving.bind( - this, - grabOp, - window, - true - ) - ); - - const id = global.display.connect('grab-op-end', () => { - global.display.disconnect(id); - // 'Quick throws' of windows won't create a tile preview since - // the timeout for onMoving may not have happened yet. So force - // 1 call of the tile preview updates for those quick actions. - this._onMoving(grabOp, window); - this._onMoveFinished(window); - }); - - // Otherwise we will update the tile preview whenever the window is - // moved as often as necessary. - } else { - this._posChangedId = window.connect('position-changed', - this._onMoving.bind( - this, - grabOp, - window, - false - ) - ); - - const id = global.display.connect('grab-op-end', () => { - global.display.disconnect(id); - this._onMoveFinished(window); - }); - } - } - } - - _onMoveFinished(window) { - if (this._posChangedId) { - window.disconnect(this._posChangedId); - this._posChangedId = 0; - } - - if (this._tileRect) { - // Ctrl-drag to replace some windows in a tile group / create a new tile group - // with at least 1 window being part of multiple tile groups. - let isCtrlReplacement = false; - const ctrlReplacedTileGroup = []; - const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); - const pointerPos = { x: global.get_pointer()[0], y: global.get_pointer()[1] }; - const twHovered = topTileGroup.some(w => w.tiledRect.containsPoint(pointerPos)); - if (this._currPreviewMode === MoveModes.ADAPTIVE_TILING && !this._splitRects.size && twHovered) { - isCtrlReplacement = true; - ctrlReplacedTileGroup.push(window); - topTileGroup.forEach(w => { - if (!this._tileRect.containsRect(w.tiledRect)) - ctrlReplacedTileGroup.push(w); - }); - } - - this._splitRects.forEach((rect, w) => Twm.tile(w, rect, { openTilingPopup: false })); - this._splitRects.clear(); - Twm.tile(window, this._tileRect, { - monitorNr: this._monitorNr, - openTilingPopup: this._currPreviewMode !== MoveModes.ADAPTIVE_TILING, - ignoreTA: this._ignoreTA - }); - this._tileRect = null; - - // Create a new tile group, in which some windows are already part - // of a different tile group, with ctrl-(super)-drag. The window may - // be maximized by ctrl-super-drag. - isCtrlReplacement && window.isTiled && Twm.updateTileGroup(ctrlReplacedTileGroup); - } else { - const restoreSetting = Settings.getInt(Settings.RESTORE_SIZE_ON); - const restoreOnEnd = restoreSetting === RestoreOn.ON_GRAB_END; - restoreOnEnd && Twm.untile( - window, { - restoreFullPos: false, - xAnchor: this._lastPointerPos.x, - skipAnim: this._wasMaximizedOnStart - } - ); - } - - this._favoriteLayout = []; - this._favoritePreviews?.forEach(p => p.destroy()); - this._favoritePreviews = []; - this._freeScreenRects = []; - this._anchorRect = null; - this._topTileGroup = null; - this._tilePreview.close(); - this._currPreviewMode = MoveModes.ADAPTIVE_TILING; - this._isGrabOp = false; - } - - // If lowPerfMode is enabled in the settings: - // Called periodically (~ every 20 ms) with a timer after a window was grabbed. - // However this function will only update the tile previews fully after about - // 500 ms. Force an earlier update, if the pointer movement state changed - // (e.g. pointer came to a stop after a movement). This Detection is done - // naively by comparing the pointer position of the previous timeout with - // the current position. - // Without the lowPerfMode enabled this will be called whenever the window is - // moved (by listening to the position-changed signal) - _onMoving(grabOp, window, lowPerfMode = false) { - const [x, y] = global.get_pointer(); - const currPointerPos = { x, y }; - - if (lowPerfMode) { - if (!this._isGrabOp) { - this._movingTimerId = null; - return GLib.SOURCE_REMOVE; - } - - const movementDist = Util.getDistance(this._lastPointerPos, currPointerPos); - const movementDetectionThreshold = 10; - let forceMoveUpdate = false; - this._movingTimeoutsSinceUpdate++; - - // Force an early update if the movement state changed - // i. e. moving -> stand still or stand still -> moving - if (this._pointerDidntMove) { - if (movementDist > movementDetectionThreshold) { - this._pointerDidntMove = false; - forceMoveUpdate = true; - } - } else if (movementDist < movementDetectionThreshold) { - this._pointerDidntMove = true; - forceMoveUpdate = true; - } - - // Only update the tile preview every 500 ms for better performance. - // Force an early update, if the pointer movement state changed. - const updateInterval = 500; - const timeSinceLastUpdate = this._movingTimerDuration * this._movingTimeoutsSinceUpdate; - if (timeSinceLastUpdate < updateInterval && !forceMoveUpdate) - return GLib.SOURCE_CONTINUE; - - this._movingTimeoutsSinceUpdate = 0; - } - - this._lastPointerPos = currPointerPos; - - const ctrl = Clutter.ModifierType.CONTROL_MASK; - const altL = Clutter.ModifierType.MOD1_MASK; - const altGr = Clutter.ModifierType.MOD5_MASK; - const meta = Clutter.ModifierType.MOD4_MASK; - const rmb = Meta.is_wayland_compositor() - ? Clutter.ModifierType.BUTTON2_MASK - : Clutter.ModifierType.BUTTON3_MASK; - const pressed = [ // idxs come from settings - false, // Dummy for disabled state so that we can use the correct idxs - Util.isModPressed(ctrl), - Util.isModPressed(altL) || Util.isModPressed(altGr), - Util.isModPressed(rmb), - Util.isModPressed(meta) - ]; - - const defaultMode = Settings.getInt(Settings.DEFAULT_MOVE_MODE); - const adaptiveMod = Settings.getInt(Settings.ADAPTIVE_TILING_MOD); - const favMod = Settings.getInt(Settings.FAVORITE_LAYOUT_MOD); - const ignoreTAMod = Settings.getInt(Settings.IGNORE_TA_MOD); - const noMod = pressed.every(modPressed => !modPressed); - - const useAdaptiveTiling = defaultMode !== MoveModes.ADAPTIVE_TILING && adaptiveMod && pressed[adaptiveMod] || - noMod && defaultMode === MoveModes.ADAPTIVE_TILING; - const usefavLayout = defaultMode !== MoveModes.FAVORITE_LAYOUT && favMod && pressed[favMod] || - noMod && defaultMode === MoveModes.FAVORITE_LAYOUT; - const useIgnoreTa = defaultMode !== MoveModes.IGNORE_TA && ignoreTAMod && pressed[ignoreTAMod] || - noMod && defaultMode === MoveModes.IGNORE_TA; - - let newMode = ''; - - if (useAdaptiveTiling) - newMode = MoveModes.ADAPTIVE_TILING; - else if (usefavLayout) - newMode = MoveModes.FAVORITE_LAYOUT; - else if (useIgnoreTa) - newMode = MoveModes.IGNORE_TA; - else - newMode = MoveModes.EDGE_TILING; - - if (this._currPreviewMode !== newMode) - this._preparePreviewModeChange(newMode, window); - - switch (newMode) { - case MoveModes.IGNORE_TA: - case MoveModes.EDGE_TILING: - this._edgeTilingPreview(window, grabOp); - break; - case MoveModes.ADAPTIVE_TILING: - this._adaptiveTilingPreview(window, grabOp); - break; - case MoveModes.FAVORITE_LAYOUT: - this._favoriteLayoutTilingPreview(window); - } - - this._currPreviewMode = newMode; - - return GLib.SOURCE_CONTINUE; - } - - _preparePreviewModeChange(newMode, window) { - this._tileRect = null; - this._ignoreTA = false; - this._topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); - - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = global.display.get_current_monitor(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - const tRects = this._topTileGroup.map(w => w.tiledRect); - this._freeScreenRects = workArea.minus(tRects); - - switch (this._currPreviewMode) { - case MoveModes.ADAPTIVE_TILING: - this._monitorNr = global.display.get_current_monitor(); - this._splitRects.clear(); - this._anchorRect = null; - break; - case MoveModes.FAVORITE_LAYOUT: - this._monitorNr = global.display.get_current_monitor(); - this._favoritePreviews.forEach(p => { - p.ease({ - opacity: 0, - duration: 100, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => p.destroy() - }); - }); - this._favoritePreviews = []; - this._anchorRect = null; - } - - switch (newMode) { - case MoveModes.IGNORE_TA: - this._ignoreTA = true; - break; - case MoveModes.FAVORITE_LAYOUT: - this._favoriteLayout = Util.getFavoriteLayout(); - this._favoriteLayout.forEach(rect => { - const tilePreview = new TilePreview(); - tilePreview.open(window, rect, this._monitorNr, { - opacity: 255, - duration: 150 - }); - this._favoritePreviews.push(tilePreview); - }); - } - } - - _restoreSizeAndRestartGrab(window, px, py, grabOp) { - Twm.untile(window, { - restoreFullPos: false, - xAnchor: px, - skipAnim: this._wasMaximizedOnStart - }); - - this._onMoveStarted(window, grabOp); - } - - /** - * Previews the rect the `window` will tile to when moving along the - * screen edges. - * - * @param {Meta.Window} window the grabbed Meta.Window. - * @param {Meta.GrabOp} grabOp the current Meta.GrabOp. - */ - _edgeTilingPreview(window, grabOp) { - // When switching monitors, provide a short grace period - // in which the tile preview will stick to the old monitor so that - // the user doesn't have to slowly inch the mouse to the monitor edge - // just because there is another monitor at that edge. - const currMonitorNr = global.display.get_current_monitor(); - const useGracePeriod = Settings.getBoolean(Settings.MONITOR_SWITCH_GRACE_PERIOD); - if (useGracePeriod) { - if (this._lastMonitorNr !== currMonitorNr) { - this._monitorNr = this._lastMonitorNr; - let timerId = 0; - this._latestMonitorLockTimerId && GLib.Source.remove(this._latestMonitorLockTimerId); - this._latestMonitorLockTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, () => { - // Only update the monitorNr, if the latest timer timed out. - if (timerId === this._latestMonitorLockTimerId) { - this._monitorNr = global.display.get_current_monitor(); - if (global.display.is_grabbed?.() || - global.display.get_grab_op?.() === grabOp) // ! - this._edgeTilingPreview(window, grabOp); - } - - this._latestMonitorLockTimerId = null; - return GLib.SOURCE_REMOVE; - }); - timerId = this._latestMonitorLockTimerId; - } - } else { - this._monitorNr = global.display.get_current_monitor(); - } - - this._lastMonitorNr = currMonitorNr; - - const wRect = window.get_frame_rect(); - const workArea = new Rect(window.get_work_area_for_monitor(this._monitorNr)); - - const vDetectionSize = Settings.getInt(Settings.VERTICAL_PREVIEW_AREA); - const pointerAtTopEdge = this._lastPointerPos.y <= workArea.y + vDetectionSize; - const pointerAtBottomEdge = this._lastPointerPos.y >= workArea.y2 - vDetectionSize; - const hDetectionSize = Settings.getInt(Settings.HORIZONTAL_PREVIEW_AREA); - const pointerAtLeftEdge = this._lastPointerPos.x <= workArea.x + hDetectionSize; - const pointerAtRightEdge = this._lastPointerPos.x >= workArea.x2 - hDetectionSize; - // Also use window's pos for top and bottom area detection for quarters - // because global.get_pointer's y isn't accurate (no idea why...) when - // grabbing the titlebar & slowly going from the left/right sides to - // the top/bottom corners. - const titleBarGrabbed = this._lastPointerPos.y - wRect.y < 50; - const windowAtTopEdge = titleBarGrabbed && wRect.y === workArea.y; - const windowAtBottomEdge = wRect.y >= workArea.y2 - 75; - const tileTopLeftQuarter = pointerAtLeftEdge && (pointerAtTopEdge || windowAtTopEdge); - const tileTopRightQuarter = pointerAtRightEdge && (pointerAtTopEdge || windowAtTopEdge); - const tileBottomLeftQuarter = pointerAtLeftEdge && (pointerAtBottomEdge || windowAtBottomEdge); - const tileBottomRightQuarter = pointerAtRightEdge && (pointerAtBottomEdge || windowAtBottomEdge); - - if (tileTopLeftQuarter) { - this._tileRect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (tileTopRightQuarter) { - this._tileRect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (tileBottomLeftQuarter) { - this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (tileBottomRightQuarter) { - this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (pointerAtTopEdge) { - // Switch between maximize & top tiling when keeping the mouse at the top edge. - const monitorRect = global.display.get_monitor_geometry(this._monitorNr); - const isLandscape = monitorRect.width >= monitorRect.height; - const shouldMaximize = - isLandscape && !Settings.getBoolean(Settings.ENABLE_HOLD_INVERSE_LANDSCAPE) || - !isLandscape && !Settings.getBoolean(Settings.ENABLE_HOLD_INVERSE_PORTRAIT); - const tileRect = shouldMaximize - ? workArea - : Twm.getTileFor(Shortcuts.TOP, workArea, this._monitorNr); - const holdTileRect = shouldMaximize - ? Twm.getTileFor(Shortcuts.TOP, workArea, this._monitorNr) - : workArea; - // Dont open preview / start new timer if preview was already one for the top - if (this._tilePreview._rect && - (holdTileRect.equal(this._tilePreview._rect) || - this._tilePreview._rect.equal(tileRect.meta))) - return; - - this._tileRect = tileRect; - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - - let timerId = 0; - this._latestPreviewTimerId && GLib.Source.remove(this._latestPreviewTimerId); - this._latestPreviewTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, - Settings.getInt(Settings.INVERSE_TOP_MAXIMIZE_TIMER), () => { - // Only open the alternative preview, if the timeout-ed timer - // is the same as the one which started last - if (timerId === this._latestPreviewTimerId && - this._tilePreview._showing && - this._tilePreview._rect.equal(tileRect.meta)) { - this._tileRect = holdTileRect; - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } - - this._latestPreviewTimerId = null; - return GLib.SOURCE_REMOVE; - }); - timerId = this._latestPreviewTimerId; - } else if (pointerAtBottomEdge) { - this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (pointerAtLeftEdge) { - this._tileRect = Twm.getTileFor(Shortcuts.LEFT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else if (pointerAtRightEdge) { - this._tileRect = Twm.getTileFor(Shortcuts.RIGHT, workArea, this._monitorNr); - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); - } else { - this._tileRect = null; - this._tilePreview.close(); - } - } - - /** - * Activates the secondary preview mode. By default, it's activated with - * `Ctrl`. When tiling using this mode, it will not only affect the grabbed - * window but possibly others as well. It's split into a 'single' and a - * 'group' mode. Take a look at _adaptiveTilingPreviewSingle() and - * _adaptiveTilingPreviewGroup() for details. - * - * @param {Meta.Window} window - * @param {Meta.GrabOp} grabOp - */ - _adaptiveTilingPreview(window, grabOp) { - if (!this._topTileGroup.length) { - this._edgeTilingPreview(window, grabOp); - return; - } - - const screenRects = this._topTileGroup - .map(w => w.tiledRect) - .concat(this._freeScreenRects); - const hoveredRect = screenRects.find(r => r.containsPoint(this._lastPointerPos)); - if (!hoveredRect) { - this._tilePreview.close(); - this._tileRect = null; - return; - } - - const isSuperPressed = Util.isModPressed(Clutter.ModifierType.MOD4_MASK); - if (isSuperPressed) { - this._anchorRect = this._anchorRect ?? hoveredRect; - this._tileRect = hoveredRect.union(this._anchorRect); - this._splitRects.clear(); - - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr, { - x: this._tileRect.x, - y: this._tileRect.y, - width: this._tileRect.width, - height: this._tileRect.height, - opacity: 200 - }); - } else { - this._anchorRect = null; - const edgeRadius = 50; - const atTopEdge = this._lastPointerPos.y < hoveredRect.y + edgeRadius; - const atBottomEdge = this._lastPointerPos.y > hoveredRect.y2 - edgeRadius; - const atLeftEdge = this._lastPointerPos.x < hoveredRect.x + edgeRadius; - const atRightEdge = this._lastPointerPos.x > hoveredRect.x2 - edgeRadius; - - atTopEdge || atBottomEdge || atLeftEdge || atRightEdge - ? this._adaptiveTilingPreviewGroup(window, hoveredRect, - { atTopEdge, atBottomEdge, atLeftEdge, atRightEdge }) - : this._adaptiveTilingPreviewSingle(window, hoveredRect); - } - } - - /** - * In this mode, when moving a window over a tiled window, the tilePreview - * will appear and (partly) cover the tiled window. If your pointer is at - * the center, the grabbed window will just tile over the hovered tiled - * window. If your pointer is hovering over the sides (but not the very - * edges) of the tiled window, the tilePreview will only cover half of the - * tiled window. Once the grabbed window is tiled, the previously hovered - * tiled window, will make space for the grabbed window by halving its size. - * - * @param {Meta.Window} window - * @param {Rect} hoveredRect - */ - _adaptiveTilingPreviewSingle(window, hoveredRect) { - const atTop = this._lastPointerPos.y < hoveredRect.y + hoveredRect.height * .25; - const atBottom = this._lastPointerPos.y > hoveredRect.y + hoveredRect.height * .75; - const atRight = this._lastPointerPos.x > hoveredRect.x + hoveredRect.width * .75; - const atLeft = this._lastPointerPos.x < hoveredRect.x + hoveredRect.width * .25; - const splitVertically = atTop || atBottom; - const splitHorizontally = atLeft || atRight; - - if (splitHorizontally || splitVertically) { - const idx = atTop && !atRight || atLeft ? 0 : 1; - const size = splitHorizontally ? hoveredRect.width : hoveredRect.height; - const orientation = splitHorizontally ? Orientation.V : Orientation.H; - this._tileRect = hoveredRect.getUnitAt(idx, size / 2, orientation); - } else { - this._tileRect = hoveredRect.copy(); - } - - if (!this._tilePreview.needsUpdate(this._tileRect)) - return; - - const monitor = global.display.get_current_monitor(); - this._tilePreview.open(window, this._tileRect.meta, monitor); - this._splitRects.clear(); - - const hoveredWindow = this._topTileGroup.find(w => { - return w.tiledRect.containsPoint(this._lastPointerPos); - }); - - if (!hoveredWindow) - return; - - // Don't halve the window, if we compelety cover it i. e. - // the user is hovering the tiled window at the center. - if (hoveredWindow.tiledRect.equal(this._tileRect)) - return; - - const splitRect = hoveredWindow.tiledRect.minus(this._tileRect)[0]; - this._splitRects.set(hoveredWindow, splitRect); - } - - /** - * Similar to _adaptiveTilingPreviewSingle(). But it's activated by hovering - * the very edges of a tiled window. And instead of affecting just 1 window - * it can possibly re-tile multiple windows. A tiled window will be affected, - * if it aligns with the edge that is being hovered. It's probably easier - * to understand, if you see it in action first rather than reading about it. - * - * @param {Meta.Window} window - * @param {Rect} hoveredRect - * @param {object} hovered contains booleans at which position the - * `hoveredRect` is hovered. - */ - _adaptiveTilingPreviewGroup(window, hoveredRect, hovered) { - // Find the smallest window that will be affected and use it to calculate - // the sizes of the preview. Determine the new tileRects for the rest - // of the tileGroup via Rect.minus(). - const smallestWindow = this._topTileGroup.reduce((smallest, w) => { - if (hovered.atTopEdge) { - if (w.tiledRect.y === hoveredRect.y || w.tiledRect.y2 === hoveredRect.y) - return w.tiledRect.height < smallest.tiledRect.height ? w : smallest; - } else if (hovered.atBottomEdge) { - if (w.tiledRect.y === hoveredRect.y2 || w.tiledRect.y2 === hoveredRect.y2) - return w.tiledRect.height < smallest.tiledRect.height ? w : smallest; - } else if (hovered.atLeftEdge) { - if (w.tiledRect.x === hoveredRect.x || w.tiledRect.x2 === hoveredRect.x) - return w.tiledRect.width < smallest.tiledRect.width ? w : smallest; - } else if (hovered.atRightEdge) { - if (w.tiledRect.x === hoveredRect.x2 || w.tiledRect.x2 === hoveredRect.x2) - return w.tiledRect.width < smallest.tiledRect.width ? w : smallest; - } - - return smallest; - }); - - const monitor = global.display.get_current_monitor(); - const workArea = new Rect(window.get_work_area_for_monitor(monitor)); - // This factor is used in combination with the smallestWindow to - // determine the final size of the grabbed window. Use half of the size - // factor, if we are at the screen edges. The cases for the bottom and - // right screen edges are covered further down. - const factor = hovered.atLeftEdge && hoveredRect.x === workArea.x || - hovered.atTopEdge && hoveredRect.y === workArea.y - ? 1 / 3 - : 2 / 3; - - // The grabbed window will be horizontal. The horizontal size (x1 - x2) - // is determined by the furthest left- and right-reaching windows that - // align with the hovered rect. The vertical size (height) is a fraction - // of the smallestWindow. - if (hovered.atTopEdge || hovered.atBottomEdge) { - const getX1X2 = alignsAt => { - return this._topTileGroup.reduce((x1x2, w) => { - const currX = x1x2[0]; - const currX2 = x1x2[1]; - return alignsAt(w) - ? [Math.min(w.tiledRect.x, currX), Math.max(w.tiledRect.x2, currX2)] - : x1x2; - }, [hoveredRect.x, hoveredRect.x2]); - }; - const alignTopEdge = w => { - return hoveredRect.y === w.tiledRect.y || - hoveredRect.y === w.tiledRect.y2; - }; - const alignBottomEdge = w => { - return hoveredRect.y2 === w.tiledRect.y2 || - hoveredRect.y2 === w.tiledRect.y; - }; - - const [x1, x2] = getX1X2(hovered.atTopEdge ? alignTopEdge : alignBottomEdge); - const size = Math.ceil(smallestWindow.tiledRect.height * factor); - // Keep within workArea bounds. - const y = Math.max(workArea.y, Math.floor(hovered.atTopEdge - ? hoveredRect.y - size / 2 - : hoveredRect.y2 - size / 2 - )); - const height = Math.min(size, workArea.y2 - y); - - this._tileRect = new Rect(x1, y, x2 - x1, height); - - // The grabbed window will be vertical. The vertical size (y1 - y2) is - // determined by the furthest top- and bottom-reaching windows that align - // with the hovered rect. The horizontal size (width) is a fraction of - // the smallestWindow. - } else { - const getY1Y2 = alignsAt => { - return this._topTileGroup.reduce((y1y2, w) => { - const currY = y1y2[0]; - const currY2 = y1y2[1]; - return alignsAt(w) - ? [Math.min(w.tiledRect.y, currY), Math.max(w.tiledRect.y2, currY2)] - : y1y2; - }, [hoveredRect.y, hoveredRect.y2]); - }; - const alignLeftEdge = w => { - return hoveredRect.x === w.tiledRect.x || - hoveredRect.x === w.tiledRect.x2; - }; - const alignRightEdge = w => { - return hoveredRect.x2 === w.tiledRect.x2 || - hoveredRect.x2 === w.tiledRect.x; - }; - - const [y1, y2] = getY1Y2(hovered.atLeftEdge ? alignLeftEdge : alignRightEdge); - const size = Math.ceil(smallestWindow.tiledRect.width * factor); - // Keep within workArea bounds. - const x = Math.max(workArea.x, Math.floor(hovered.atLeftEdge - ? hoveredRect.x - size / 2 - : hoveredRect.x2 - size / 2 - )); - const width = Math.min(size, workArea.x2 - x); - - this._tileRect = new Rect(x, y1, width, y2 - y1); - } - - this._tileRect.tryAlignWith(workArea); - - if (!this._tilePreview.needsUpdate(this._tileRect)) - return; - - this._tilePreview.open(window, this._tileRect.meta, monitor); - this._splitRects.clear(); - - this._topTileGroup.forEach(w => { - const leftOver = w.tiledRect.minus(this._tileRect); - const splitRect = leftOver[0]; - // w isn't an affected window. - if (splitRect?.equal(this._tileRect) ?? true) - return; - - this._splitRects.set(w, splitRect); - }); - } - - _favoriteLayoutTilingPreview(window) { - // Holding Super will make the window span multiple rects of the favorite - // layout starting from the rect, which the user starting holding Super in. - const isSuperPressed = Util.isModPressed(Clutter.ModifierType.MOD4_MASK); - for (const rect of this._favoriteLayout) { - if (rect.containsPoint(this._lastPointerPos)) { - if (isSuperPressed) { - this._anchorRect = this._anchorRect ?? rect; - this._tileRect = rect.union(this._anchorRect); - } else { - this._tileRect = rect.copy(); - this._anchorRect = null; - } - - this._tilePreview.open(window, this._tileRect.meta, this._monitorNr, { - x: this._tileRect.x, - y: this._tileRect.y, - width: this._tileRect.width, - height: this._tileRect.height, - opacity: 200 - }); - return; - } - } - - this._tileRect = null; - this._tilePreview.close(); - } -} - -const TilePreview = GObject.registerClass( -class TilePreview extends WindowManager.TilePreview { - _init() { - super._init(); - this.set_style_class_name('tile-preview'); - } - - needsUpdate(rect) { - return !this._rect || !rect.equal(this._rect); - } - - // Added param for animation and removed style for rounded corners - open(window, tileRect, monitorIndex, animateTo = undefined) { - const windowActor = window.get_compositor_private(); - if (!windowActor) - return; - - global.window_group.set_child_below_sibling(this, windowActor); - - if (this._rect && this._rect.equal(tileRect)) - return; - - const changeMonitor = this._monitorIndex === -1 || - this._monitorIndex !== monitorIndex; - - this._monitorIndex = monitorIndex; - this._rect = tileRect; - - const monitor = Main.layoutManager.monitors[monitorIndex]; - - if (!this._showing || changeMonitor) { - const monitorRect = new Mtk.Rectangle({ - x: monitor.x, - y: monitor.y, - width: monitor.width, - height: monitor.height - }); - const [, rect] = window.get_frame_rect().intersect(monitorRect); - this.set_size(rect.width, rect.height); - this.set_position(rect.x, rect.y); - this.opacity = 0; - } - - this._showing = true; - this.show(); - - if (!animateTo) { - animateTo = { - x: tileRect.x, - y: tileRect.y, - width: tileRect.width, - height: tileRect.height, - opacity: 255, - duration: WINDOW_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }; - } else { - animateTo.x === undefined && this.set_x(tileRect.x); - animateTo.y === undefined && this.set_y(tileRect.y); - animateTo.width === undefined && this.set_width(tileRect.width); - animateTo.height === undefined && this.set_height(tileRect.height); - animateTo.opacity === undefined && this.set_opacity(255); - animateTo.duration = animateTo.duration ?? WINDOW_ANIMATION_TIME; - animateTo.mode = animateTo.mode ?? Clutter.AnimationMode.EASE_OUT_QUAD; - } - - this.ease(animateTo); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js deleted file mode 100644 index 2400fe2..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js +++ /dev/null @@ -1,534 +0,0 @@ -import { Clutter, Meta } from '../dependencies/gi.js'; - -import { Orientation, Settings } from '../common.js'; -import { Rect, Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -const Side = { - NONE: 0, - SAME_H: 1, - OPPOSING_H: 2, - SAME_V: 4, - OPPOSING_V: 8 -}; - -/** - * This class gets to handle the resize events of windows (whether they are - * tiled or not). If a window isn't tiled, nothing happens. If the resized - * window is tiled, auto-resize the complementing tiled windows. Intercardinal - * resizing is split into its [H]orizontal and [V]ertical components. - */ - -export default class TilingResizeHandler { - constructor() { - const isResizing = grabOp => { - switch (grabOp) { - case Meta.GrabOp.RESIZING_N: - case Meta.GrabOp.RESIZING_NW: - case Meta.GrabOp.RESIZING_NE: - case Meta.GrabOp.RESIZING_S: - case Meta.GrabOp.RESIZING_SW: - case Meta.GrabOp.RESIZING_SE: - case Meta.GrabOp.RESIZING_E: - case Meta.GrabOp.RESIZING_W: - return true; - - default: - return false; - } - }; - - const g1 = global.display.connect('grab-op-begin', (d, window, grabOp) => { - grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED - - if (window && isResizing(grabOp)) - this._onResizeStarted(window, grabOp); - }); - const g2 = global.display.connect('grab-op-end', (d, window, grabOp) => { - grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED - - if (window && isResizing(grabOp)) - this._onResizeFinished(window, grabOp); - }); - this._displaySignals = []; - this._displaySignals.push(g1); - this._displaySignals.push(g2); - - this._sizeChangedId = 0; - this._preGrabRects = new Map(); - // Save the windows, which are to be resized (passively) along the - // actively grabbed one, and a resizeOp. A resizeOp saves the side - // of the window, which will be passively resized, relative to the - // actively resized window. - this._resizeOps = new Map(); - } - - destroy() { - this._displaySignals.forEach(sId => global.display.disconnect(sId)); - } - - _onResizeStarted(window, grabOp) { - if (!window.isTiled) - return; - - // Use the same margin for the alignment and equality check below. - const margin = 5; - let topTileGroup = Twm.getTopTileGroup(); - topTileGroup.forEach(w => { - this._preGrabRects.set(w, new Rect(w.get_frame_rect())); - - if (w !== window) - // There is no snapping for tiled windows, if the user set a window - // gap. So the windows may not align properly, if the user tried - // to manually resize them to be edge to edge. In that case, assume - // that windows that are within a certain margin distance to each - // other are meant to align and resize them together. - w.tiledRect.tryAlignWith(window.tiledRect, margin); - }); - - // Windows can be part of multiple tile groups. We however only resize - // the top most visible tile group. That means a tile group in a lower - // stack position may share windows with the top tile group and after - // the resize op those windows will no longer match with the lower tile - // group's tiles. So remove the shared windows from the lower tile group. - const allWindows = Twm.getWindows(); - allWindows.forEach(w => { - if (!w.isTiled) - return; - - if (topTileGroup.includes(w)) - return; - - // Gets a tile group of windows without the ones - // which are about to be resized - const group = Twm.getTileGroupFor(w); - const newGroup = group.reduce((gr, win) => { - !topTileGroup.includes(win) && gr.push(win); - return gr; - }, []); - - // Tile groups are the same - if (group.length === newGroup.length) - return; - - // Remove old tile group and create new one - Twm.clearTilingProps(w.get_id()); - Twm.updateTileGroup(newGroup); - }); - - // Remove the actively resizing window to get the windows, which will - // be passively resized. - topTileGroup.splice(topTileGroup.indexOf(window), 1); - const grabbedRect = window.tiledRect; - - // Holding Ctrl allows resizing windows which only directly (or transitively) - // border the window being actively resized (instead of the entire tileGroup) - const isCtrlPressed = Util.isModPressed(Clutter.ModifierType.CONTROL_MASK); - const singleEdgeResizeOp = [ - Meta.GrabOp.RESIZING_N, - Meta.GrabOp.RESIZING_S, - Meta.GrabOp.RESIZING_W, - Meta.GrabOp.RESIZING_E - ]; - if (isCtrlPressed && singleEdgeResizeOp.includes(grabOp)) - topTileGroup = this._getWindowsForIndividualResize(window, topTileGroup, grabOp); - - switch (grabOp) { - // Resizing cardinal directions - case Meta.GrabOp.RESIZING_N: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y, otherRect.y, margin), - Util.equal(grabbedRect.y, otherRect.y2, margin), - false, - false - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, grabOp, null)); - break; - - case Meta.GrabOp.RESIZING_S: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y2, otherRect.y2, margin), - Util.equal(grabbedRect.y2, otherRect.y, margin), - false, - false - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, grabOp, null)); - break; - - case Meta.GrabOp.RESIZING_E: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - false, - false, - Util.equal(grabbedRect.x2, otherRect.x2, margin), - Util.equal(grabbedRect.x2, otherRect.x, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, null, grabOp)); - break; - - case Meta.GrabOp.RESIZING_W: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - false, - false, - Util.equal(grabbedRect.x, otherRect.x, margin), - Util.equal(grabbedRect.x, otherRect.x2, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, null, grabOp)); - break; - - // Resizing intercardinal directions: - case Meta.GrabOp.RESIZING_NW: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y, otherRect.y, margin), - Util.equal(grabbedRect.y, otherRect.y2, margin), - Util.equal(grabbedRect.x, otherRect.x, margin), - Util.equal(grabbedRect.x, otherRect.x2, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_W)); - break; - - case Meta.GrabOp.RESIZING_NE: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y, otherRect.y, margin), - Util.equal(grabbedRect.y, otherRect.y2, margin), - Util.equal(grabbedRect.x2, otherRect.x2, margin), - Util.equal(grabbedRect.x2, otherRect.x, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_E)); - break; - - case Meta.GrabOp.RESIZING_SW: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y2, otherRect.y2, margin), - Util.equal(grabbedRect.y2, otherRect.y, margin), - Util.equal(grabbedRect.x, otherRect.x, margin), - Util.equal(grabbedRect.x, otherRect.x2, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_S, Meta.GrabOp.RESIZING_W)); - break; - - case Meta.GrabOp.RESIZING_SE: - for (const otherWindow of topTileGroup) { - const otherRect = otherWindow.tiledRect; - const resizeOp = ResizeOp.createResizeOp( - Util.equal(grabbedRect.y2, otherRect.y2, margin), - Util.equal(grabbedRect.y2, otherRect.y, margin), - Util.equal(grabbedRect.x2, otherRect.x2, margin), - Util.equal(grabbedRect.x2, otherRect.x, margin) - ); - resizeOp && this._resizeOps.set(otherWindow, resizeOp); - } - - this._sizeChangedId = window.connect('size-changed', - this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_S, Meta.GrabOp.RESIZING_E)); - } - } - - // Update the windows' tiledRects - _onResizeFinished(window, grabOp) { - if (this._sizeChangedId) { - window.disconnect(this._sizeChangedId); - this._sizeChangedId = 0; - } - - if (!window.isTiled) - return; - - const monitor = window.get_monitor(); - const screenTopGap = Util.useIndividualGaps(monitor) - ? Util.getScaledGap(Settings.SCREEN_TOP_GAP, monitor) - : Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); - const screenLeftGap = Util.useIndividualGaps(monitor) - ? Util.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor) - : Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); - const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, monitor); - const workArea = window.get_work_area_for_monitor(monitor); - - // First calculate the new tiledRect for window: - // The new x / y coord for the window's tiledRect can be calculated by - // a simple difference because resizing on the E / S side won't change - // x / y and resizing on the N or W side will translate into a 1:1 shift - const grabbedsNewRect = new Rect(window.get_frame_rect()); - const grabbedsOldRect = this._preGrabRects.get(window); - - const isResizingW = (grabOp & Meta.GrabOp.RESIZING_W) > 1; - // Shift the tiledRect by the resize amount - let newGrabbedTiledRectX = window.tiledRect.x + (grabbedsNewRect.x - grabbedsOldRect.x); - // Switch the screenGap for a windowGap - if (isResizingW && window.tiledRect.x === workArea.x) - newGrabbedTiledRectX = newGrabbedTiledRectX + screenLeftGap - windowGap / 2; - - // Same as W but different orientation - const isResizingN = (grabOp & Meta.GrabOp.RESIZING_N) > 1; - let newGrabbedTiledRectY = window.tiledRect.y + (grabbedsNewRect.y - grabbedsOldRect.y); - if (isResizingN && window.tiledRect.y === workArea.y) - newGrabbedTiledRectY = newGrabbedTiledRectY + screenTopGap - windowGap / 2; - - // If resizing on the E side, you can simply rely on get_frame_rect's - // new width else x2 should stick to where it was (manual calc due - // special cases like gnome-terminal) - const isResizingE = (grabOp & Meta.GrabOp.RESIZING_E) > 1; - const newGrabbedTiledRectWidth = isResizingE - ? grabbedsNewRect.width + windowGap / 2 + (workArea.x === newGrabbedTiledRectX ? screenLeftGap : windowGap / 2) - : window.tiledRect.x2 - newGrabbedTiledRectX; - - // Same principal applies to the height and resizing on the S side - const isResizingS = (grabOp & Meta.GrabOp.RESIZING_S) > 1; - const newGrabbedTiledRectHeight = isResizingS - ? grabbedsNewRect.height + windowGap / 2 + (workArea.y === newGrabbedTiledRectY ? screenTopGap : windowGap / 2) - : window.tiledRect.y2 - newGrabbedTiledRectY; - - const grabbedsOldTiledRect = window.tiledRect; - window.tiledRect = new Rect( - newGrabbedTiledRectX, - newGrabbedTiledRectY, - newGrabbedTiledRectWidth, - newGrabbedTiledRectHeight - ); - - // Now calculate the new tiledRects for the windows, which were resized - // along the window based on the diff of the window's tiledRect pre - // and after the grab. - const tiledRectDiffX = window.tiledRect.x - grabbedsOldTiledRect.x; - const tiledRectDiffY = window.tiledRect.y - grabbedsOldTiledRect.y; - const tiledRectDiffWidth = window.tiledRect.width - grabbedsOldTiledRect.width; - const tiledRectDiffHeight = window.tiledRect.height - grabbedsOldTiledRect.height; - - this._resizeOps.forEach((resizeOp, win) => { - if (win === window) - return; - - if (resizeOp.side & Side.SAME_H) { - win.tiledRect.x += tiledRectDiffX; - win.tiledRect.width += tiledRectDiffWidth; - } else if (resizeOp.side & Side.OPPOSING_H) { - win.tiledRect.x += isResizingE ? tiledRectDiffWidth : 0; - win.tiledRect.width -= tiledRectDiffWidth; - } - - if (resizeOp.side & Side.SAME_V) { - win.tiledRect.y += tiledRectDiffY; - win.tiledRect.height += tiledRectDiffHeight; - } else if (resizeOp.side & Side.OPPOSING_V) { - win.tiledRect.y += isResizingS ? tiledRectDiffHeight : 0; - win.tiledRect.height -= tiledRectDiffHeight; - } - }); - - this._preGrabRects.clear(); - this._resizeOps.clear(); - } - - _onResizing(resizedWindow, grabOpV, grabOpH) { - this._resizeOps.forEach((resizeOp, window) => { - const rectV = this._getPassiveResizedRect(grabOpV, resizedWindow, window, - resizeOp.side & Side.SAME_V, resizeOp.side & Side.OPPOSING_V); - - const rectH = this._getPassiveResizedRect(grabOpH, resizedWindow, window, - resizeOp.side & Side.SAME_H, resizeOp.side & Side.OPPOSING_H); - - if (rectV && rectH) - window.move_resize_frame(false, rectH[0], rectV[1], rectH[2], rectV[3]); - else if (rectV) - window.move_resize_frame(false, ...rectV); - else if (rectH) - window.move_resize_frame(false, ...rectH); - }); - } - - // Gets the rect for the non-grabbed window adapted to the resized - // grabbed window *but* only adapted for 1 side (either vertically - // or horizontally) at a time based on grabOp - _getPassiveResizedRect(grabOp, resizedWindow, window, - resizeOnSameSide, resizeOnOpposingSide) { - if (!grabOp) - return null; - - if (!resizeOnSameSide && !resizeOnOpposingSide) - return null; - - const resizedRect = new Rect(resizedWindow.get_frame_rect()); - const wRect = new Rect(window.get_frame_rect()); - const preGrabRect = this._preGrabRects.get(window); - const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, window.get_monitor()); - - switch (grabOp) { - case Meta.GrabOp.RESIZING_N: - return resizeOnSameSide - ? [wRect.x, resizedRect.y, wRect.width, preGrabRect.y2 - resizedRect.y] - : [wRect.x, wRect.y, wRect.width, resizedRect.y - wRect.y - windowGap]; - - case Meta.GrabOp.RESIZING_S: - return resizeOnSameSide - ? [wRect.x, wRect.y, wRect.width, resizedRect.y2 - preGrabRect.y] - : [wRect.x, resizedRect.y2 + windowGap, wRect.width, preGrabRect.y2 - resizedRect.y2 - windowGap]; - - case Meta.GrabOp.RESIZING_W: - return resizeOnSameSide - ? [resizedRect.x, wRect.y, preGrabRect.x2 - resizedRect.x, wRect.height] - : [wRect.x, wRect.y, resizedRect.x - wRect.x - windowGap, wRect.height]; - - case Meta.GrabOp.RESIZING_E: - return resizeOnSameSide - ? [wRect.x, wRect.y, resizedRect.x2 - preGrabRect.x, wRect.height] - : [resizedRect.x2 + windowGap, wRect.y, preGrabRect.x2 - resizedRect.x2 - windowGap, wRect.height]; - } - } - - /** - * Gets the windows which should be resized for the 'individual' resize mode. - * That means all windows that directly (or transitively) border the window - * being resized at the resized edge. - * - * @param {Meta.Window} window the window that is actively resized. - * @param {Meta.Window[]} tileGroup the top tile group. - * @param {Meta.GrabOp} grabOp - * @returns {Meta.Window[]} all windows that will resize using the individual resize mode - */ - _getWindowsForIndividualResize(window, tileGroup, grabOp) { - // Resizes on the same side as the one being resized by the user. - // Starts with the window that is actively being resized by the user. - const sameSide = [window]; - // Resizes on the opposite side as the one being resized by the user - const oppositeSide = []; - const resizeIsNOrW = [Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_W].includes(grabOp); - const orientation = [Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_S].includes(grabOp) - ? Orientation.V : Orientation.H; - - // Checks if the w1 and w2 border each other at a certain edge. - const borders = (w1, w2, w1IsAfterW2) => { - const [start, end] = orientation === Orientation.H ? ['x', 'x2'] : ['y', 'y2']; - const overlap = orientation === Orientation.H ? 'vertOverlap' : 'horizOverlap'; - if (w1IsAfterW2) { - return w1.tiledRect[start] === w2.tiledRect[end] && - w1.tiledRect[overlap](w2.tiledRect); - } else { - return w1.tiledRect[end] === w2.tiledRect[start] && - w1.tiledRect[overlap](w2.tiledRect); - } - }; - - /** - * @param {Meta.Window[]} uncheckedWindows windows yet to be checked. - * @param {Meta.Window[]} checkingWindows windows, which the bordering windows - * are searched for. It initially only starts with the window that is - * actively resized by the user. - * @param {Meta.Window[]} borderingWindows the windows that border the - * checkingWindows on the resized edge. - * @param {boolean} sideDeterminant determines which edge the - * bordering is checked on. It's the relation of the checkingWindows - * to the actively resized windows. - */ - const findBorderingWindows = (uncheckedWindows, checkingWindows, - borderingWindows, sideDeterminant) => { - const oldCount = borderingWindows.length; - - checkingWindows.forEach(w => { - uncheckedWindows.forEach(unchecked => { - if (borders(w, unchecked, sideDeterminant)) - borderingWindows.push(unchecked); - }); - }); - - if (oldCount !== borderingWindows.length) { - // Find the bordering windows for the newly added windows by - // flipping the checkingWindows and borderingWindows arrays as well as - // the side that is checked with the borders function. - findBorderingWindows( - uncheckedWindows.filter(w => !borderingWindows.includes(w)), - borderingWindows, - checkingWindows, - !sideDeterminant - ); - } - }; - - findBorderingWindows(tileGroup, sameSide, oppositeSide, resizeIsNOrW); - return [...sameSide, ...oppositeSide]; - } -} - -/** - * Saves information on which side a window will resize to complement the - * grabbed window. A non-grabbed window can resize on the 'same side', on - * the 'opposing side' or not at all. For ex.: Resizing the top-left quarter - * on the E side means the bottom-left quarter resizes on the same side (E) - * and the top / bottom-right quarters resize on the opposing side (W). If - * the bottom window wasn't quartered but instead had its width equal the - * workArea.width, then it wouldn't resize at all. - */ -const ResizeOp = class ResizeOp { - /** - * @param {number} side - */ - constructor(side) { - this.side = side; - } - - /** - * @param {boolean} resizeOnSameSideV - * @param {boolean} resizeOnOpposingSideV - * @param {boolean} resizeOnSameSideH - * @param {boolean} resizeOnOpposingSideH - * @returns {ResizeOp|null} - */ - static createResizeOp(resizeOnSameSideV, resizeOnOpposingSideV, - resizeOnSameSideH, resizeOnOpposingSideH) { - let verticalResizeSide = Side.NONE; - let horizontalResizeSide = Side.NONE; - - if (resizeOnSameSideV) - verticalResizeSide = Side.SAME_V; - else if (resizeOnOpposingSideV) - verticalResizeSide = Side.OPPOSING_V; - - if (resizeOnSameSideH) - horizontalResizeSide = Side.SAME_H; - else if (resizeOnOpposingSideH) - horizontalResizeSide = Side.OPPOSING_H; - - const resizeSide = verticalResizeSide | horizontalResizeSide; - return resizeSide ? new ResizeOp(resizeSide) : null; - } -}; diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js deleted file mode 100644 index 599d85e..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js +++ /dev/null @@ -1,774 +0,0 @@ -import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; -import { _, Main } from '../dependencies/shell.js'; - -import { Direction, Orientation, Settings } from '../common.js'; -import { Rect, Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; - -const SCALE_SIZE = 100; -const Modes = { - DEFAULT: 1, - SWAP: 2, - RESIZE: 4, - MOVE: 8, - CLOSE: 16 -}; - -/** - * Classes for the 'Tile Editing Mode'. A mode to manage your tiled windows - * with your keyboard (and only the keyboard). The Tile Editor gets instanced - * as soon as the keyboard shortcut is activated. The Handler classes are - * basically modes / states for the Tile Editor each with a 'on key press' and - * 'on key released' function. - */ - -export const TileEditor = GObject.registerClass( -class TileEditingMode extends St.Widget { - _init() { - super._init({ reactive: true }); - - this._haveModal = false; - // The windows managed by the Tile Editor, that means the tiled windows - // that aren't overlapped by other windows; in other words: the top tile Group - this._windows = []; - // Indicate the active selection by the user. Added to `this`. - this._selectIndicator = null; - this._mode = Modes.DEFAULT; - // Handler of keyboard events depending on the mode. - this._keyHandler = null; - - Main.uiGroup.add_child(this); - - this.connect('key-press-event', (__, event) => - this._onKeyPressEvent(event)); - } - - open() { - this._windows = Twm.getTopTileGroup(); - - const grab = Main.pushModal(this); - // We expect at least a keyboard grab here - if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { - Main.popModal(grab); - return false; - } - - this._grab = grab; - this._haveModal = true; - - const openWindows = Twm.getWindows(); - if (!openWindows.length || !this._windows.length) { - const msg = _("Can't enter 'Tile Editing Mode', if no tiled window is visible."); - Main.notify('Tiling Assistant', msg); - this.close(); - return; - } - - this.monitor = this._windows[0].get_monitor(); - const display = global.display.get_monitor_geometry(this.monitor); - this.set_position(display.x, display.y); - this.set_size(display.width, display.height); - - // Enter initial state. - this._mode = Modes.DEFAULT; - this._keyHandler = new DefaultKeyHandler(this); - - // The windows may not be at the foreground. They just weren't - // overlapping other windows. So raise the entire tile group. - this._windows.forEach(w => w.raise_and_make_recent()); - - // Create the active selection indicator. - const window = this._windows[0]; - const params = { style_class: 'tile-preview' }; - this._selectIndicator = new Indicator(window.tiledRect, this.monitor, params); - this._selectIndicator.focus(window.tiledRect, window); - this.add_child(this._selectIndicator); - } - - close() { - if (this._haveModal) { - Main.popModal(this._grab); - this._haveModal = false; - } - - this._windows = []; - this._keyHandler = null; - - // this._selectIndicator may be undefined, if Tile Editing Mode is - // left as soon as it's entered (e. g. when there's no tile group). - this._selectIndicator?.window?.activate(global.get_current_time()); - this._selectIndicator?.ease({ - x: this._selectIndicator.x + SCALE_SIZE / 2, - y: this._selectIndicator.y + SCALE_SIZE / 2, - width: this._selectIndicator.width - SCALE_SIZE, - height: this._selectIndicator.height - SCALE_SIZE, - opacity: 0, - duration: 150, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => this.destroy() - }) ?? this.destroy(); - } - - vfunc_button_press_event() { - this._keyHandler.prepareLeave(); - this.close(); - } - - async _onKeyPressEvent(keyEvent) { - const mods = keyEvent.get_state(); - let newMode; - - // Swap windows - if (mods & Clutter.ModifierType.CONTROL_MASK) - newMode = Modes.SWAP; - // Move group to different workspace / monitor - else if (mods & Clutter.ModifierType.SHIFT_MASK) - newMode = Modes.MOVE; - // Resize windows - else if (mods & Clutter.ModifierType.MOD4_MASK) - newMode = Modes.RESIZE; - // Default keys - else - newMode = Modes.DEFAULT; - - // First switch mode, if a new mod is pressed. - if (newMode !== this._mode) - this._switchMode(newMode); - - // Handle the key press and get mode depending on that. - newMode = await this._keyHandler.handleKeyPress(keyEvent); - - if (newMode && newMode !== this._mode) - this._switchMode(newMode); - } - - vfunc_key_release_event(keyEvent) { - const newMode = this._keyHandler.handleKeyRelease(keyEvent); - if (newMode && newMode !== this._mode) - this._switchMode(newMode); - } - - _switchMode(newMode) { - if (!newMode) - return; - - this._mode = newMode; - this._keyHandler.prepareLeave(); - - switch (newMode) { - case Modes.DEFAULT: - this._keyHandler = new DefaultKeyHandler(this); - break; - case Modes.SWAP: - this._keyHandler = new SwapKeyHandler(this); - break; - case Modes.MOVE: - this._keyHandler = new MoveKeyHandler(this); - break; - case Modes.RESIZE: - this._keyHandler = new ResizeKeyHandler(this); - break; - case Modes.CLOSE: - this.close(); - } - } -}); - -/** - * Indicate the user selection or other stuff. - */ -const Indicator = GObject.registerClass(class TileEditingModeIndicator extends St.Widget { - /** - * @param {string} widgetParams - * @param {Rect} rect the final rect / pos of the indicator - * @param {number} monitor - */ - _init(rect, monitor, widgetParams = {}) { - // Start from a scaled down position. - super._init({ - ...widgetParams, - x: rect.x + SCALE_SIZE / 2, - y: rect.y + SCALE_SIZE / 2, - width: rect.width - SCALE_SIZE, - height: rect.height - SCALE_SIZE, - opacity: 0 - }); - - this.rect = null; - this.window = null; - this._monitor = monitor; - } - - /** - * Animate the indicator to a specific position. - * - * @param {Rect} rect the position the indicator will animate to. - * @param {Meta.Window|null} window the window at `rect`'s position. - */ - focus(rect, window = null) { - const display = global.display.get_monitor_geometry(this._monitor); - const activeWs = global.workspace_manager.get_active_workspace(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(this._monitor)); - - // Adjusted for window / screen gaps - const { x, y, width, height } = rect.addGaps(workArea); - - this.ease({ - x: x - display.x, - y: y - display.y, - width, - height, - opacity: 255, - duration: 150, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }); - - this.rect = rect; - this.window = window; - } -}); - -/** - * Base class for other keyboard handlers and the default handler itself. - * - * @param {TileEditingMode} tileEditor - */ -const DefaultKeyHandler = class DefaultKeyHandler { - constructor(tileEditor) { - this._tileEditor = tileEditor; - } - - /** - * Automatically called when leaving a mode. - */ - prepareLeave() { - } - - /** - * Automatically called on a keyEvent. - * - * @param {number} keyEvent - * @returns {Modes} The mode to enter after the event was handled. - */ - async handleKeyPress(keyEvent) { - const keyVal = keyEvent.get_key_symbol(); - - // [Directions] to move focus with WASD, hjkl or arrow keys - const dir = Util.getDirection(keyVal); - if (dir) { - this._focusInDir(dir); - - // [E]xpand to fill the available space - } else if (keyVal === Clutter.KEY_e || keyVal === Clutter.KEY_E) { - const window = this._selectIndicator.window; - if (!window) - return Modes.DEFAULT; - - const tiledRect = this._windows.map(w => w.tiledRect); - const tileRect = Twm.getBestFreeRect(tiledRect, { currRect: window.tiledRect }); - if (window.tiledRect.equal(tileRect)) - return Modes.DEFAULT; - - const workArea = window.get_work_area_current_monitor(); - const maximize = tileRect.equal(workArea); - if (maximize && this._windows.length > 1) - return Modes.DEFAULT; - - Twm.tile(window, tileRect, { openTilingPopup: false }); - - if (maximize) - return Modes.CLOSE; - - this._selectIndicator.focus(window.tiledRect, window); - - // [C]ycle through halves of the available space around the window - } else if (keyVal === Clutter.KEY_c || keyVal === Clutter.KEY_C) { - const window = this._selectIndicator.window; - if (!window) - return Modes.DEFAULT; - - const tiledRects = this._windows.map(w => w.tiledRect); - const fullRect = Twm.getBestFreeRect(tiledRects, { currRect: window.tiledRect }); - const topHalf = fullRect.getUnitAt(0, fullRect.height / 2, Orientation.H); - const rightHalf = fullRect.getUnitAt(1, fullRect.width / 2, Orientation.V); - const bottomHalf = fullRect.getUnitAt(1, fullRect.height / 2, Orientation.H); - const leftHalf = fullRect.getUnitAt(0, fullRect.width / 2, Orientation.V); - const rects = [topHalf, rightHalf, bottomHalf, leftHalf]; - const currIdx = rects.findIndex(r => r.equal(window.tiledRect)); - const newIndex = (currIdx + 1) % 4; - - Twm.tile(window, rects[newIndex], { openTilingPopup: false }); - this._selectIndicator.focus(window.tiledRect, window); - - // [Q]uit a window - } else if (keyVal === Clutter.KEY_q || keyVal === Clutter.KEY_Q) { - const window = this._selectIndicator.window; - if (!window) - return Modes.DEFAULT; - - this._windows.splice(this._windows.indexOf(window), 1); - window.delete(global.get_current_time()); - const newWindow = this._windows[0]; - if (!newWindow) - return Modes.CLOSE; - - this._selectIndicator.focus(newWindow.tiledRect, newWindow); - - // [R]estore a window's size - } else if (keyVal === Clutter.KEY_r || keyVal === Clutter.KEY_R) { - const window = this._selectIndicator.window; - if (!window) - return Modes.DEFAULT; - - const selectedRect = window.tiledRect.copy(); - this._windows.splice(this._windows.indexOf(window), 1); - Twm.untile(window); - if (!this._windows.length) - return Modes.CLOSE; - - // Re-raise tile group, so it isn't below the just-untiled window - this._windows[0].raise_and_make_recent(); - this._selectIndicator.focus(selectedRect, null); - - // [Enter] / [Esc]ape Tile Editing Mode - } else if (keyVal === Clutter.KEY_Escape || keyVal === Clutter.KEY_Return) { - return Modes.CLOSE; - - // [Space] to activate the Tiling Popup - } else if (keyVal === Clutter.KEY_space) { - const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); - const openWindows = Twm.getWindows(allWs).filter(w => !this._windows.includes(w)); - const TilingPopup = await import('./tilingPopup.js'); - const tilingPopup = new TilingPopup.TilingSwitcherPopup( - openWindows, - this._selectIndicator.rect, - false - ); - - if (!tilingPopup.show(this._windows)) { - tilingPopup.destroy(); - return Modes.DEFAULT; - } - - tilingPopup.connect('closed', (popup, canceled) => { - if (canceled) - return; - - const { tiledWindow } = popup; - const replaced = this._windows.findIndex(w => w.tiledRect.equal(tiledWindow.tiledRect)); - replaced !== -1 && this._windows.splice(replaced, 1); - - // Create the new tile group to allow 1 window to be part of multiple tile groups - Twm.updateTileGroup([tiledWindow, ...this._windows]); - - this._windows.unshift(tiledWindow); - this._selectIndicator.focus(tiledWindow.tiledRect, tiledWindow); - }); - } - - return Modes.DEFAULT; - } - - /** - * Automatically called on a keyEvent. - * - * @param {number} keyEvent - * @returns {Modes|undefined} The mode to enter after the event was handled. - */ - handleKeyRelease() { - return undefined; - } - - /** - * Move the the selection indicator towards direction of `dir`. - * - * @param {Direction} dir - */ - _focusInDir(dir) { - const activeWs = global.workspace_manager.get_active_workspace(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(this._tileEditor.monitor)); - const tiledRects = this._windows.map(w => w.tiledRect); - const screenRects = tiledRects.concat(workArea.minus(tiledRects)); - const nearestRect = this._selectIndicator.rect.getNeighbor(dir, screenRects); - if (!nearestRect) - return; - - const newWindow = this._windows.find(w => w.tiledRect.equal(nearestRect)); - this._selectIndicator.focus(newWindow?.tiledRect ?? nearestRect, newWindow); - } - - get _windows() { - return this._tileEditor._windows; - } - - get _selectIndicator() { - return this._tileEditor._selectIndicator; - } -}; - -/** - * Move the selected window to a different position. If there is a window at - * the new position, the 2 windows will swap their positions. - * - * @param {TileEditingMode} tileEditor - */ -const SwapKeyHandler = class SwapKeyHandler extends DefaultKeyHandler { - constructor(tileEditor) { - super(tileEditor); - - // Create an 'anchor indicator' to indicate the window that will be swapped - const color = this._selectIndicator.get_theme_node().get_background_color(); - const { red, green, blue, alpha } = color; - this._anchorIndicator = new Indicator(this._selectIndicator.rect, tileEditor.monitor, { - style: `background-color: rgba(${red}, ${green}, ${blue}, ${alpha / 255})` - }); - this._anchorIndicator.focus(this._selectIndicator.rect, this._selectIndicator.window); - this._tileEditor.add_child(this._anchorIndicator); - } - - prepareLeave() { - this._anchorIndicator.destroy(); - } - - handleKeyPress(keyEvent) { - const direction = Util.getDirection(keyEvent.get_key_symbol()); - - // [Directions] to choose a window to swap with WASD, hjkl or arrow keys - if (direction) - this._focusInDir(direction); - - // [Esc]ape Tile Editing Mode - else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) - return Modes.DEFAULT; - - return Modes.SWAP; - } - - handleKeyRelease(keyEvent) { - const keyVal = keyEvent.get_key_symbol(); - const ctrlKeys = [Clutter.KEY_Control_L, Clutter.KEY_Control_R]; - - if (ctrlKeys.includes(keyVal)) { - this._swap(); - return Modes.DEFAULT; - } - - return Modes.SWAP; - } - - _swap() { - if (this._anchorIndicator.window) - { Twm.tile(this._anchorIndicator.window, this._selectIndicator.rect, { - openTilingPopup: false - }); } - - if (this._selectIndicator.window) - { Twm.tile(this._selectIndicator.window, this._anchorIndicator.rect, { - openTilingPopup: false - }); } - - this._selectIndicator.focus(this._selectIndicator.rect, - this._anchorIndicator.window); - } -}; - -/** - * Move the tile group to a different workspace / monitor. - * - * @param {TileEditingMode} tileEditor - */ -const MoveKeyHandler = class MoveKeyHandler extends DefaultKeyHandler { - handleKeyPress(keyEvent) { - const direction = Util.getDirection(keyEvent.get_key_symbol()); - const moveWorkspace = keyEvent.get_state() & Clutter.ModifierType.MOD1_MASK; - - // [Directions] to move the tile group - if (direction) { - // To new workspace - if (moveWorkspace) { - let metaDir = Meta.MotionDirection.UP; - if (direction === Direction.N) - metaDir = Meta.MotionDirection.UP; - else if (direction === Direction.S) - metaDir = Meta.MotionDirection.DOWN; - else if (direction === Direction.W) - metaDir = Meta.MotionDirection.LEFT; - else if (direction === Direction.E) - metaDir = Meta.MotionDirection.RIGHT; - - const activeWs = global.workspace_manager.get_active_workspace(); - const newWs = activeWs.get_neighbor(metaDir); - if (activeWs === newWs) - return Modes.MOVE; - - Twm.moveGroupToWorkspace(this._tileEditor._windows, newWs); - - // To new monitor - } else { - let metaDir = Meta.DisplayDirection.UP; - if (direction === Direction.N) - metaDir = Meta.DisplayDirection.UP; - else if (direction === Direction.S) - metaDir = Meta.DisplayDirection.DOWN; - else if (direction === Direction.W) - metaDir = Meta.DisplayDirection.LEFT; - else if (direction === Direction.E) - metaDir = Meta.DisplayDirection.RIGHT; - - // get_current_monitor isn't accurate for our case - const currMonitor = this._tileEditor.monitor; - const newMonitor = global.display.get_monitor_neighbor_index(currMonitor, metaDir); - if (newMonitor === -1) - return Modes.MOVE; - - Twm.moveGroupToMonitor(this._tileEditor._windows, currMonitor, newMonitor); - } - - return Modes.CLOSE; - - // [Esc] to return to default mode - } else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) { - return Modes.DEFAULT; - } - - return Modes.MOVE; - } -}; - -/** - * Handler to resize the highlighted window. - * - * @param {TileEditor} tileEditor - */ -const ResizeKeyHandler = class ResizeKeyHandler extends DefaultKeyHandler { - constructor(tileEditor) { - super(tileEditor); - - // The edge that is currently being resized. - this._currEdge = null; - this._resizeSideIndicator = null; - } - - prepareLeave() { - this._resizeSideIndicator?.destroy(); - } - - handleKeyPress(keyEvent) { - // [Directions] to resize with WASD, hjkl or arrow keys - const direction = Util.getDirection(keyEvent.get_key_symbol()); - if (direction) { - const window = this._selectIndicator.window; - if (!window) - return Modes.DEFAULT; - - // First call: Go to an edge. - if (!this._currEdge) { - this._currEdge = direction; - this._createResizeIndicator(); - return Modes.RESIZE; - - // Change resize orientation from H to V - } else if ([Direction.N, Direction.S].includes(this._currEdge)) { - if ([Direction.W, Direction.E].includes(direction)) { - this._currEdge = direction; - this._createResizeIndicator(); - return Modes.RESIZE; - } - - // Change resize orientation from V to H - } else if ([Direction.W, Direction.E].includes(this._currEdge)) { - if ([Direction.N, Direction.S].includes(direction)) { - this._currEdge = direction; - this._createResizeIndicator(); - return Modes.RESIZE; - } - } - - this._resize(window, direction); - - // Update the selection indicator. - this._selectIndicator.focus(window.tiledRect, window); - - // Update resize side indicator - this._resizeSideIndicator.updatePos(window.tiledRect); - - // [Esc]ape Tile Editing Mode - } else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) { - return Modes.CLOSE; - } - - return Modes.RESIZE; - } - - handleKeyRelease(keyEvent) { - const keyVal = keyEvent.get_key_symbol(); - const superKeys = [Clutter.KEY_Super_L, Clutter.KEY_Super_R]; - return superKeys.includes(keyVal) ? Modes.DEFAULT : Modes.RESIZE; - } - - _resize(window, keyDir) { - // Rect, which is being resized by the user. But it still has - // its original / pre-resize dimensions - const resizedRect = window.tiledRect; - const workArea = new Rect(window.get_work_area_current_monitor()); - let resizeAmount = 50; - - // Limit resizeAmount to the workArea - if (this._currEdge === Direction.N && keyDir === Direction.N) - resizeAmount = Math.min(resizeAmount, resizedRect.y - workArea.y); - else if (this._currEdge === Direction.S && keyDir === Direction.S) - resizeAmount = Math.min(resizeAmount, workArea.y2 - resizedRect.y2); - else if (this._currEdge === Direction.W && keyDir === Direction.W) - resizeAmount = Math.min(resizeAmount, resizedRect.x - workArea.x); - else if (this._currEdge === Direction.E && keyDir === Direction.E) - resizeAmount = Math.min(resizeAmount, workArea.x2 - resizedRect.x2); - - if (resizeAmount <= 0) - return; - - // Function to update the passed rect by the resizeAmount depending on - // the edge that is resized. Some windows will resize on the same edge - // as the one the user is resizing. Other windows will resize on the - // opposite edge. - const updateRectSize = (rect, resizeOnEdge) => { - const growDir = keyDir === resizeOnEdge ? 1 : -1; - switch (resizeOnEdge) { - case Direction.N: - rect.y -= resizeAmount * growDir; - // falls through - case Direction.S: - rect.height += resizeAmount * growDir; - break; - - case Direction.W: - rect.x -= resizeAmount * growDir; - // falls through - case Direction.E: - rect.width += resizeAmount * growDir; - } - }; - - // Actually resize the windows here. - this._windows.forEach(w => { - // The window, which is resized by the user, is included in this. - if (this._isSameSide(resizedRect, w.tiledRect)) { - const newRect = w.tiledRect.copy(); - updateRectSize(newRect, this._currEdge); - Twm.tile(w, newRect, { openTilingPopup: false }); - } else if (this._isOppositeSide(resizedRect, w.tiledRect)) { - const newRect = w.tiledRect.copy(); - updateRectSize(newRect, Direction.opposite(this._currEdge)); - Twm.tile(w, newRect, { openTilingPopup: false }); - } - }); - } - - _isOppositeSide(rect1, rect2) { - switch (this._currEdge) { - case Direction.N: - return rect1.y === rect2.y2; - case Direction.S: - return rect1.y2 === rect2.y; - case Direction.W: - return rect1.x === rect2.x2; - case Direction.E: - return rect1.x2 === rect2.x; - } - - return false; - } - - _isSameSide(rect1, rect2) { - switch (this._currEdge) { - case Direction.N: - return rect1.y === rect2.y; - case Direction.S: - return rect1.y2 === rect2.y2; - case Direction.W: - return rect1.x === rect2.x; - case Direction.E: - return rect1.x2 === rect2.x2; - } - - return false; - } - - _createResizeIndicator() { - this._resizeSideIndicator?.destroy(); - this._resizeSideIndicator = new ResizeSideIndicator( - this._currEdge, this._selectIndicator.rect); - Main.uiGroup.add_child(this._resizeSideIndicator); - } -}; - -const ResizeSideIndicator = GObject.registerClass( -class ResizeSideIndicator extends St.Widget { - _init(edge, activeRect) { - const [width, height] = [Direction.N, Direction.S].includes(edge) - ? [200, 20] - : [20, 200]; - - super._init({ - width, - height, - opacity: 0, - style: 'background-color: black;\ - border-radius: 999px;' - }); - - this._edge = edge; - this._moveDist = 100; - - this.updatePos(activeRect); - - // Inner pill - const innerWidth = this.width < this.height ? 4 : 75; - const innerHeight = this.width < this.height ? 75 : 4; - this.add_child(new St.Widget({ - x: this.width / 2 - innerWidth / 2, - y: this.height / 2 - innerHeight / 2, - width: innerWidth, - height: innerHeight, - style: 'background-color: #ebebeb;\ - border-radius: 999px;' - })); - } - - destroy() { - this.ease({ - opacity: 0, - duration: 100, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => super.destroy() - }); - } - - updatePos(rect) { - let x, y; - switch (this._edge) { - case Direction.N: - x = rect.center.x - this.width / 2; - y = rect.y - this.height / 2; - break; - case Direction.S: - x = rect.center.x - this.width / 2; - y = rect.y2 - this.height / 2; - break; - case Direction.W: - x = rect.x - this.width / 2; - y = rect.center.y - this.height / 2; - break; - case Direction.E: - x = rect.x2 - this.width / 2; - y = rect.center.y - this.height / 2; - } - - this.ease({ - x, - y, - opacity: 255, - duration: 150, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingPopup.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingPopup.js deleted file mode 100644 index 72afd45..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingPopup.js +++ /dev/null @@ -1,352 +0,0 @@ -import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; -import { Main, SwitcherPopup } from '../dependencies/shell.js'; - -import { Direction, Orientation } from '../common.js'; -import { Util } from './utility.js'; -import { TilingWindowManager as Twm } from './tilingWindowManager.js'; -import * as AltTab from './altTab.js'; - -/** - * Classes for the Tiling Popup, which opens when tiling a window - * and there is free screen space to fill with other windows. - * Mostly based on GNOME's altTab.js - */ - -export const TilingSwitcherPopup = GObject.registerClass({ - Signals: { - // Bool indicates whether the Tiling Popup was canceled - // (or if a window was tiled with this popup) - 'closed': { param_types: [GObject.TYPE_BOOLEAN] } - } -}, class TilingSwitcherPopup extends AltTab.TilingAppSwitcherPopup { - /** - * @param {Meta.Windows[]} openWindows an array of Meta.Windows, which this - * popup offers to tile. - * @param {Rect} freeScreenRect the Rect, which the popup will tile a window - * to. The popup will be centered in this rect. - * @param {boolean} allowConsecutivePopup allow the popup to create another - * Tiling Popup, if there is still unambiguous free screen space after - * this popup tiled a window. - */ - _init(openWindows, freeScreenRect, allowConsecutivePopup = true) { - this._freeScreenRect = freeScreenRect; - this._shadeBG = null; - this._monitor = -1; - - SwitcherPopup.SwitcherPopup.prototype._init.call(this); - - this._thumbnails = null; - this._thumbnailTimeoutId = 0; - this._currentWindow = -1; - this.thumbnailsVisible = false; - // The window, which was tiled with the Tiling Popup after it's closed - // or null, if the popup was closed with tiling a window - this.tiledWindow = null; - this._allowConsecutivePopup = allowConsecutivePopup; - - this._switcherList = new TSwitcherList(this, openWindows); - this._items = this._switcherList.icons; - - // Destroy popup when touching outside of popup - this.connect('touch-event', () => { - if (Meta.is_wayland_compositor()) - this.fadeAndDestroy(); - - return Clutter.EVENT_PROPAGATE; - }); - } - - /** - * @param {Array} tileGroup an array of Meta.Windows. When the popup - * appears it will shade the background. These windows will won't - * be affected by that. - * @returns if the popup was successfully shown. - */ - show(tileGroup) { - this._monitor = tileGroup[0]?.get_monitor() ?? global.display.get_current_monitor(); - - if (!this._items.length) - return false; - - const grab = Main.pushModal(this); - // We expect at least a keyboard grab here - if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { - Main.popModal(grab); - return false; - } - - this._grab = grab; - this._haveModal = true; - - this._switcherList.connect('item-activated', this._itemActivated.bind(this)); - this._switcherList.connect('item-entered', this._itemEntered.bind(this)); - this._switcherList.connect('item-removed', this._itemRemoved.bind(this)); - this.add_actor(this._switcherList); - - // Need to force an allocation so we can figure out - // whether we need to scroll when selecting - this.visible = true; - this.get_allocation_box(); - - this._select(0); - - Main.osdWindowManager.hideAll(); - - this._shadeBackground(tileGroup); - this.opacity = 0; - this.ease({ - opacity: 255, - duration: 200, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }); - - return true; - } - - _shadeBackground(tileGroup) { - const tiledWindow = tileGroup[0]; - const activeWs = global.workspace_manager.get_active_workspace(); - const workArea = activeWs.get_work_area_for_monitor(this._monitor); - - this._shadeBG = new St.Widget({ - style: 'background-color : black', - x: workArea.x, - y: workArea.y, - width: workArea.width, - height: workArea.height, - opacity: 0 - }); - global.window_group.add_child(this._shadeBG); - this._shadeBG.ease({ - opacity: 180, - duration: 200, - mode: Clutter.AnimationMode.EASE_OUT_QUAD - }); - - if (!tiledWindow) - return; - - // Clones to correctly shade the background for consecutive tiling. - for (let i = 1; i < tileGroup.length; i++) { - const wActor = tileGroup[i].get_compositor_private(); - const clone = new Clutter.Clone({ - source: wActor, - x: wActor.x, - y: wActor.y - }); - global.window_group.add_child(clone); - wActor.hide(); - this.connect('destroy', () => { - wActor.show(); - clone.destroy(); - }); - } - - const tActor = tiledWindow.get_compositor_private(); - global.window_group.set_child_above_sibling(tActor, this._shadeBG); - } - - vfunc_allocate(box) { - this.set_allocation(box); - - const freeScreenRect = this._freeScreenRect; - const childBox = new Clutter.ActorBox(); - - const leftPadding = this.get_theme_node().get_padding(St.Side.LEFT); - const rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT); - const hPadding = leftPadding + rightPadding; - - const [, childNaturalHeight] = this._switcherList.get_preferred_height( - freeScreenRect.width - hPadding); - const [, childNaturalWidth] = this._switcherList.get_preferred_width(childNaturalHeight); - - childBox.x1 = Math.max(freeScreenRect.x + leftPadding, - freeScreenRect.x + Math.floor((freeScreenRect.width - childNaturalWidth) / 2)); - childBox.x2 = Math.min(freeScreenRect.x2 - rightPadding, - childBox.x1 + childNaturalWidth); - childBox.y1 = freeScreenRect.y + Math.floor((freeScreenRect.height - childNaturalHeight) / 2); - childBox.y2 = childBox.y1 + childNaturalHeight; - - this._switcherList.allocate(childBox); - - if (this._thumbnails) { - const cbox = this._switcherList.get_allocation_box(); - const monitor = global.display.get_monitor_geometry(this._monitor); - - const leftPadd = this.get_theme_node().get_padding(St.Side.LEFT); - const rightPadd = this.get_theme_node().get_padding(St.Side.RIGHT); - const bottomPadding = this.get_theme_node().get_padding(St.Side.BOTTOM); - const hPadd = leftPadd + rightPadd; - - const icon = this._items[this._selectedIndex]; - const [posX] = icon.get_transformed_position(); - const thumbnailCenter = posX + icon.width / 2; - const [, cNatWidth] = this._thumbnails.get_preferred_width(-1); - cbox.x1 = Math.max(monitor.x + leftPadd, - Math.floor(thumbnailCenter - cNatWidth / 2) - ); - if (cbox.x1 + cNatWidth > monitor.x + monitor.width - hPadd) { - const offset = cbox.x1 + cNatWidth - monitor.width + hPadd; - cbox.x1 = Math.max(monitor.x + leftPadd, cbox.x1 - offset - hPadd); - } - - const spacing = this.get_theme_node().get_length('spacing'); - - cbox.x2 = cbox.x1 + cNatWidth; - if (cbox.x2 > monitor.x + monitor.width - rightPadd) - cbox.x2 = monitor.x + monitor.width - rightPadd; - cbox.y1 = this._switcherList.allocation.y2 + spacing; - this._thumbnails.addClones(monitor.y + monitor.height - bottomPadding - cbox.y1); - const [, cNatHeight] = this._thumbnails.get_preferred_height(-1); - cbox.y2 = cbox.y1 + cNatHeight; - - this._thumbnails.allocate(cbox); - } - } - - vfunc_button_press_event(buttonEvent) { - const btn = buttonEvent.get_button(); - if (btn === Clutter.BUTTON_MIDDLE || btn === Clutter.BUTTON_SECONDARY) { - this._finish(global.get_current_time()); - return Clutter.EVENT_PROPAGATE; - } - - return super.vfunc_button_press_event(buttonEvent); - } - - _keyPressHandler(keysym) { - const moveUp = Util.isDirection(keysym, Direction.N); - const moveDown = Util.isDirection(keysym, Direction.S); - const moveLeft = Util.isDirection(keysym, Direction.W); - const moveRight = Util.isDirection(keysym, Direction.E); - - if (this._thumbnailsFocused) { - if (moveLeft) - this._select(this._selectedIndex, this._previousWindow()); - else if (moveRight) - this._select(this._selectedIndex, this._nextWindow()); - else if (moveUp || moveDown) - this._select(this._selectedIndex, null, true); - else - return Clutter.EVENT_PROPAGATE; - } else if (moveLeft) { - this._select(this._previous()); - } else if (moveRight) { - this._select(this._next()); - } else if (moveDown || moveUp) { - this._select(this._selectedIndex, 0); - } else { - return Clutter.EVENT_PROPAGATE; - } - - return Clutter.EVENT_STOP; - } - - _windowActivated(thumbnailSwitcher, n) { - const window = this._items[this._selectedIndex].cachedWindows[n]; - this._tileWindow(window); - this.fadeAndDestroy(); - } - - _finish(timestamp) { - const appIcon = this._items[this._selectedIndex]; - const window = appIcon.cachedWindows[Math.max(0, this._currentWindow)]; - this._tileWindow(window); - SwitcherPopup.SwitcherPopup.prototype._finish.call(this, timestamp); - } - - fadeAndDestroy() { - if (this._alreadyDestroyed) - return; - - this._alreadyDestroyed = true; - - const canceled = !this.tiledWindow; - this.emit('closed', canceled); - - this._shadeBG?.destroy(); - this._shadeBG = null; - super.fadeAndDestroy(); - } - - _tileWindow(window) { - let rect = this._freeScreenRect; - - // Halve the tile rect. - // If isShiftPressed, then put the window at the top / left side; - // if isAltPressed, then put it at the bottom / right side. - // The orientation depends on the available screen space. - const isShiftPressed = Util.isModPressed(Clutter.ModifierType.SHIFT_MASK); - const isAltPressed = Util.isModPressed(Clutter.ModifierType.MOD1_MASK); - if (isShiftPressed || isAltPressed) { - // Prefer vertical a bit more (because screens are usually horizontal) - const vertical = rect.width >= rect.height * 1.25; - const size = vertical ? 'width' : 'height'; - const orientation = vertical ? Orientation.V : Orientation.H; - const idx = isShiftPressed ? 0 : 1; - rect = rect.getUnitAt(idx, rect[size] / 2, orientation); - } - - this.tiledWindow = window; - - window.change_workspace(global.workspace_manager.get_active_workspace()); - - // We want to activate/focus the window after it was tiled with the - // Tiling Popup. Calling activate/focus() after tile() doesn't seem to - // work for GNOME Terminal if it is maximized before trying to tile it. - // It won't be tiled properly in that case for some reason... Instead - // activate first but clear the tiling signals before so that the old - // tile group won't be accidentally raised. - Twm.clearTilingProps(window.get_id()); - window.activate(global.get_current_time()); - Twm.tile(window, rect, { monitorNr: this._monitor, openTilingPopup: this._allowConsecutivePopup }); - } - - // Dont _finish(), if no mods are pressed - _resetNoModsTimeout() { - } -}); - -const TSwitcherList = GObject.registerClass( -class TilingSwitcherList extends AltTab.TilingAppSwitcher { - _setIconSize() { - let j = 0; - while (this._items.length > 1 && this._items[j].style_class !== 'item-box') - j++; - - const themeNode = this._items[j].get_theme_node(); - this._list.ensure_style(); - - const iconPadding = themeNode.get_horizontal_padding(); - const iconBorder = themeNode.get_border_width(St.Side.LEFT) + - themeNode.get_border_width(St.Side.RIGHT); - const [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1); - const iconSpacing = labelNaturalHeight + iconPadding + iconBorder; - const totalSpacing = this._list.spacing * (this._items.length - 1); - - const freeScreenRect = this._altTabPopup._freeScreenRect; - const parentPadding = this.get_parent().get_theme_node().get_horizontal_padding(); - const availWidth = freeScreenRect.width - parentPadding - - this.get_theme_node().get_horizontal_padding(); - - const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - const baseIconSizes = [96, 64, 48, 32, 22]; - const iconSizes = baseIconSizes.map(s => s * scaleFactor); - let iconSize = baseIconSizes[0]; - - if (this._items.length > 1) { - for (let i = 0; i < baseIconSizes.length; i++) { - iconSize = baseIconSizes[i]; - const height = iconSizes[i] + iconSpacing; - const w = height * this._items.length + totalSpacing; - if (w <= availWidth) - break; - } - } - - this._iconSize = iconSize; - - for (let i = 0; i < this.icons.length; i++) - this.icons[i].set_size(iconSize); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js deleted file mode 100644 index 730ee8a..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js +++ /dev/null @@ -1,1339 +0,0 @@ -import { Clutter, GLib, GObject, Meta, Mtk, Shell } from '../dependencies/gi.js'; -import { Main } from '../dependencies/shell.js'; -import { getWindows } from '../dependencies/unexported/altTab.js'; - -import { Orientation, Settings, Shortcuts } from '../common.js'; -import { Rect, Util } from './utility.js'; - -/** - * Singleton responsible for tiling. Implement the signals in a separate Clutter - * class so this doesn't need to be instanced. - */ -export class TilingWindowManager { - static initialize() { - this._signals = new TilingSignals(); - - // { windowId1: [windowIdX, windowIdY, ...], windowId2: [...], ... } - this._tileGroups = new Map(); - - // [windowIds] - this._unmanagingWindows = []; - - this._wsAddedId = global.workspace_manager.connect('workspace-added', this._onWorkspaceAdded.bind(this)); - this._wsRemovedId = global.workspace_manager.connect('workspace-removed', this._onWorkspaceRemoved.bind(this)); - } - - static destroy() { - this._signals.destroy(); - this._signals = null; - - global.workspace_manager.disconnect(this._wsAddedId); - global.workspace_manager.disconnect(this._wsRemovedId); - - this._tileGroups.clear(); - this._unmanagingWindows = []; - - if (this._openAppTiledTimerId) { - GLib.Source.remove(this._openAppTiledTimerId); - this._openAppTiledTimerId = null; - } - - if (this._wsAddedTimer) { - GLib.Source.remove(this._wsAddedTimer); - this._wsAddedTimer = null; - } - - if (this._wsRemovedTimer) { - GLib.Source.remove(this._wsRemovedTimer); - this._wsRemovedTimer = null; - } - } - - static connect(signal, func) { - return this._signals.connect(signal, func); - } - - static disconnect(id) { - this._signals.disconnect(id); - } - - static emit(...params) { - this._signals.emit(...params); - } - - /** - * Gets windows, which can be tiled - * - * @param {boolean} [allWorkspaces=false] determines whether we only want - * the windows from the current workspace. - * @returns {Meta.Windows[]} an array of of the open Meta.Windows in - * stacking order. - */ - static getWindows(allWorkspaces = false) { - const activeWs = global.workspace_manager.get_active_workspace(); - const openWindows = getWindows(allWorkspaces ? null : activeWs); - // The open windows are not sorted properly when tiling with the Tiling - // Popup because altTab sorts by focus. - const sorted = global.display.sort_windows_by_stacking(openWindows); - return sorted.reverse().filter(w => { - // I don't think this should normally happen but if it does, this - // extension can crash GNOME Shell.. so guard against it. A way to - // have a window's monitor be -1, for example, is explained here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4713 - if (w.get_monitor() === -1) - return false; - - // Assumption: a maximized window can also resize (once unmaximized) - const canResize = w.allows_move() && w.allows_resize() || this.isMaximized(w); - return canResize; - }); - } - - /** - * @param {Meta.Window} window a Meta.Window. - * @param {Meta.WorkArea|Rect|null} workArea useful for the grace period - * @returns whether the window is maximized. Be it using GNOME's native - * maximization or the maximization by this extension when using gaps. - */ - static isMaximized(window, workArea = null) { - const area = workArea ?? window.get_work_area_current_monitor(); - return window.get_maximized() === Meta.MaximizeFlags.BOTH || - window.tiledRect?.equal(area); - } - - /** - * Tiles a window to a specific spot and setup all tiling properties. - * - * @param {Meta.Window} window a Meta.Window to tile. - * @param {Rect} newRect the Rect the `window` will be tiled to. - * @param {boolean} [openTilingPopup=true] decides, if we open a Tiling - * Popup after the window is tiled and there is unambiguous free - * screen space. - * @param {number} [number=null] is used to get the workArea in which the - * window tiles on. It's used for gap calculation. We can't always rely on - * window.get_monitor with its monitor or global.display.get_current_monitor - * (the pointer monitor) because of the 'grace period' during a quick dnd - * towards a screen border since the pointer and the window will be on the - * 'wrong' monitor. - * @param {boolean} [skipAnim=false] decides, if we skip the tile animation. - * @param {boolean} [tileGroup=null] forces the creation of this tile group. - * @param {boolean} [fakeTile=false] don't create a new tile group, don't - * emit 'tiled' signal or open the Tiling Popup - */ - static async tile(window, newRect, { - openTilingPopup = true, - ignoreTA = false, - monitorNr = null, - skipAnim = false, - fakeTile = false - } = {}) { - if (!window || window.is_skip_taskbar()) - return; - - const wasMaximized = window.get_maximized(); - if (wasMaximized) - window.unmaximize(wasMaximized); - - window.unmake_fullscreen(); - - if (!window.allows_resize() || !window.allows_move()) - return; - - // Remove window from the other windows' tileGroups so it - // doesn't falsely get raised with them. - this.clearTilingProps(window.get_id()); - - window.unmake_above(); - window.unminimize(); - // Raise window since tiling with the popup means that - // the window can be below others. - window.raise_and_make_recent(); - - const oldRect = new Rect(window.get_frame_rect()); - const monitor = monitorNr ?? window.get_monitor(); - const workArea = new Rect(window.get_work_area_for_monitor(monitor)); - const maximize = newRect.equal(workArea); - - window.isTiled = !maximize; - if (!window.untiledRect) - window.untiledRect = oldRect; - - if (maximize && !Settings.getBoolean(Settings.MAXIMIZE_WITH_GAPS)) { - window.tiledRect = null; - // It's possible for a window to maximize() to the wrong monitor. - // This is very easy to reproduce when dragging a window on the - // lower half with Super + LMB. - window.move_to_monitor(monitor); - window.maximize(Meta.MaximizeFlags.BOTH); - return; - } - - // Save the intended tiledRect for accurate operations later. - // Workaround for windows which can't be resized freely... - // For ex. which only resize in full rows/columns like gnome-terminal - window.tiledRect = newRect.copy(); - - const { x, y, width, height } = newRect.addGaps(workArea, monitor); - - // Animations - const wActor = window.get_compositor_private(); - if (Settings.getBoolean(Settings.ENABLE_TILE_ANIMATIONS) && wActor && !skipAnim) { - wActor.remove_all_transitions(); - // HACK => journalctl: 'error in size change accounting'...? - // TODO: no animation if going from maximized -> tiled and back to back multiple times? - Main.wm._prepareAnimationInfo( - global.window_manager, - wActor, - oldRect.meta, - Meta.SizeChange.MAXIMIZE - ); - } - - // See issue #137. - // Under some circumstances it's possible that windows will tile to the wrong - // monitor. I can't reproduce it but I suspect that it's because of passing - // false as the user_op to move_resize_frame. user_op is meant to determine if - // the window should be clamped to the monitor. A user operation (user_op = true) - // won't be clamped. So I think there is something unexpected happening. - // Someone in the issue mentioned that passing true as the user_op fixes the - // multi-monitor bug. - // - // The reason why I set user_op as false originally is that GNOME Terminal (and - // some other Terminals) will only resize but not move with user_op as true. Try - // to workaround that by first only moving the window and then resizing it. That - // workaround was already necessary under Wayland because of some apps. E. g. - // first tiling Nautilus and then Firefox using the Tiling Popup. - window.move_to_monitor(monitor); - window.move_frame(true, x, y); - window.move_resize_frame(true, x, y, width, height); - - // Maximized with gaps - if (maximize) { - this._updateGappedMaxWindowSignals(window); - - // Tiled window - } else if (!fakeTile) { - // Make the tile group only consist of the window itself to stop - // resizing or raising together. Also don't call the Tiling Popup. - if (Settings.getBoolean(Settings.DISABLE_TILE_GROUPS) || ignoreTA) { - this.updateTileGroup([window]); - return; - } - - // Setup the (new) tileGroup to raise tiled windows as a group - const topTileGroup = this._getWindowsForBuildingTileGroup(monitor); - this.updateTileGroup(topTileGroup); - - this.emit('window-tiled', window); - - if (openTilingPopup) - await this.tryOpeningTilingPopup(); - } - } - - /** - * Untiles a tiled window and delete all tiling properties. - * - * @param {Meta.Window} window a Meta.Window to untile. - * @param {boolean} [restoreFullPos=true] decides, if we restore the - * pre-tile position or whether the size while keeping the titlebar - * at the relative same position. - * @param {number} [xAnchor=undefined] used when wanting to restore the - * size while keeping titlebar at the relative x position. By default, - * we use the pointer position. - * @param {boolean} [skipAnim=false] decides, if we skip the until animation. - */ - static untile(window, { restoreFullPos = true, xAnchor = undefined, skipAnim = false, clampToWorkspace = false } = {}) { - const wasMaximized = window.get_maximized(); - if (wasMaximized) - window.unmaximize(wasMaximized); - - if (!window.untiledRect || !window.allows_resize() || !window.allows_move()) - return; - - // If you tiled a window and then used the popup to tile more - // windows, the consecutive windows will be raised above the first - // one. So untiling the initial window after tiling more windows with - // the popup (without re-focusing the initial window), means the - // untiled window will be below the others. - window.raise_and_make_recent(); - - // Animation - const untileAnim = Settings.getBoolean(Settings.ENABLE_UNTILE_ANIMATIONS); - const wActor = window.get_compositor_private(); - if (untileAnim && !wasMaximized && wActor && !skipAnim) { - wActor.remove_all_transitions(); - Main.wm._prepareAnimationInfo( - global.window_manager, - wActor, - window.get_frame_rect(), - Meta.SizeChange.UNMAXIMIZE - ); - } - - // userOp means that the window won't clamp to the workspace. For DND - // we don't want to clamp to the workspace, so it's false by default. - const userOp = !clampToWorkspace; - const oldRect = window.untiledRect; - if (restoreFullPos) { - window.move_resize_frame(userOp, oldRect.x, oldRect.y, oldRect.width, oldRect.height); - } else { - // Resize the window while keeping the relative x pos (of the pointer) - const currWindowFrame = new Rect(window.get_frame_rect()); - xAnchor = xAnchor ?? global.get_pointer()[0]; - const relativeMouseX = (xAnchor - currWindowFrame.x) / currWindowFrame.width; - const newPosX = xAnchor - oldRect.width * relativeMouseX; - - // Wayland workaround for DND / restore position - Meta.is_wayland_compositor() && window.move_frame(true, newPosX, currWindowFrame.y); - - window.move_resize_frame(userOp, newPosX, currWindowFrame.y, oldRect.width, oldRect.height); - } - - this.clearTilingProps(window.get_id()); - window.isTiled = false; - window.tiledRect = null; - window.untiledRect = null; - - this.emit('window-untiled', window); - } - - /** - * Moves the tile group to a different workspace - * - * @param {Meta.Window[]} tileGroup - * @param {Meta.Workspace} workspace - */ - static moveGroupToWorkspace(tileGroup, workspace) { - tileGroup.forEach(w => { - this._blockTilingSignalsFor(w); - w.change_workspace(workspace); - this._unblockTilingSignalsFor(w); - }); - } - - /** - * Moves the tile group to a different monitor - * - * @param {Meta.Window[]} tileGroup - * @param {number} oldMon - * @param {number} newMon - */ - static moveGroupToMonitor(tileGroup, oldMon, newMon) { - const activeWs = global.workspace_manager.get_active_workspace(); - const oldWorkArea = new Rect(activeWs.get_work_area_for_monitor(oldMon)); - const newWorkArea = new Rect(activeWs.get_work_area_for_monitor(newMon)); - - const hScale = oldWorkArea.width / newWorkArea.width; - const vScale = oldWorkArea.height / newWorkArea.height; - - tileGroup.forEach((w, idx) => { - const newTile = w.tiledRect.copy(); - newTile.x = newWorkArea.x + Math.floor(newWorkArea.width * ((w.tiledRect.x - oldWorkArea.x) / oldWorkArea.width)); - newTile.y = newWorkArea.y + Math.floor(newWorkArea.height * ((w.tiledRect.y - oldWorkArea.y) / oldWorkArea.height)); - newTile.width = Math.floor(w.tiledRect.width * (1 / hScale)); - newTile.height = Math.floor(w.tiledRect.height * (1 / vScale)); - - // Try to align with all previously scaled tiles and the workspace to prevent gaps - for (let i = 0; i < idx; i++) - newTile.tryAlignWith(tileGroup[i].tiledRect); - - newTile.tryAlignWith(newWorkArea, 10); - - this.tile(w, newTile, { - skipAnim: true, - fakeTile: true - }); - }); - - // The tiling signals got disconnected during the tile() call but not - // (re-)connected with it since it may have been possible that wrong tile - // groups would have been created when moving one window after the other - // to the new monitor. So update the tileGroup now with the full/old group. - this.updateTileGroup(tileGroup); - } - - /** - * @returns {Map} - * For ex: { windowId1: [windowIdX, windowIdY, ...], windowId2: ... } - */ - static getTileGroups() { - return this._tileGroups; - } - - /** - * @param {Map} tileGroups - * For ex: { windowId1: [windowIdX, windowIdY, ...], windowId2: ... } - */ - static setTileGroups(tileGroups) { - this._tileGroups = tileGroups; - } - - /** - * Creates a tile group of windows to raise them together, if one of them - * is raised by (re)connecting signals. Usually, this is done automatically - * by calling tile() and thus shouldn't be done manually. tile() only allows - * unique/non-overlapping tile groups, so 1 window can't be part of multiple - * tile groups. But we specifically allow the user to do that sometimes - * (i. e. ctrl-drag or tile editing mode+space). So manually create the - * tile group in those cases. - * - * @param {Meta.Windows[]} tileGroup an array of Meta.Windows to group - * together. - */ - static updateTileGroup(tileGroup) { - tileGroup.forEach(window => { - const windowId = window.get_id(); - const signals = this._signals.getSignalsFor(windowId); - - this._tileGroups.set(windowId, tileGroup.map(w => w.get_id())); - - /** - * clearTilingProps may have been called before this function, - * so we need to reconnect all the signals on the tileGroup. - * Just in case, also try to disconnect old signals... - */ - - // Reconnect unmanaging signal - const unmanagingSignal = signals.get(TilingSignals.UNMANAGING); - unmanagingSignal && window.disconnect(unmanagingSignal); - - const umId = window.connect('unmanaging', w => { - this.clearTilingProps(windowId); - this._unmanagingWindows.push(w.get_stable_sequence()); - }); - signals.set(TilingSignals.UNMANAGING, umId); - - // Reconnect ws-changed signal - const wsChangeSignal = signals.get(TilingSignals.WS_CHANGED); - wsChangeSignal && window.disconnect(wsChangeSignal); - - const wsId = window.connect('workspace-changed', () => this._onWindowWorkspaceChanged(window)); - signals.set(TilingSignals.WS_CHANGED, wsId); - - // Reconnect raise signal - const raiseSignal = signals.get(TilingSignals.RAISE); - raiseSignal && window.disconnect(raiseSignal); - - const raiseId = window.connect('raised', raisedWindow => { - const raisedWindowId = raisedWindow.get_id(); - if (Settings.getBoolean(Settings.RAISE_TILE_GROUPS)) { - const raisedWindowsTileGroup = this._tileGroups.get(raisedWindowId); - raisedWindowsTileGroup.forEach(wId => { - const w = this._getWindow(wId); - const otherRaiseId = this._signals.getSignalsFor(wId).get(TilingSignals.RAISE); - // May be undefined, if w was just closed. This would - // automatically call clearTilingProps() with the signal - // but in case I missed / don't know about other cases where - // w may be nullish, dissolve the tileGroups anyway. - if (!w || !otherRaiseId) { - this.clearTilingProps(wId); - return; - } - - // Prevent an infinite loop of windows raising each other - w.block_signal_handler(otherRaiseId); - w.raise_and_make_recent(); - w.unblock_signal_handler(otherRaiseId); - }); - - // Re-raise the just raised window so it may not be below - // other tiled windows otherwise when untiling via keyboard - // it may be below other tiled windows. - const signalId = this._signals.getSignalsFor(raisedWindowId).get(TilingSignals.RAISE); - raisedWindow.block_signal_handler(signalId); - raisedWindow.raise_and_make_recent(); - raisedWindow.unblock_signal_handler(signalId); - } - - // Update the tileGroup (and reconnect the raised signals) to allow windows - // to be part of multiple tileGroups: for ex.: tiling a window over another - // tiled window with ctrl-drag will replace the overlapped window in the old - // tileGroup but the overlapped window will remember its old tile group to - // raise them as well, if it is raised. - const raisedTileGroup = this.getTileGroupFor(raisedWindow); - this.updateTileGroup(raisedTileGroup); - }); - signals.set(TilingSignals.RAISE, raiseId); - }); - } - - /** - * Deletes the tile group of a window and remove that window from other - * tiled windows' tile groups. Also disconnects the signals for windows - * which are maximized-with-gaps. - * - * @param {number} windowId the id of a Meta.Window. - */ - static clearTilingProps(windowId) { - const window = this._getWindow(windowId); - const signals = this._signals.getSignalsFor(windowId); - - if (signals.get(TilingSignals.RAISE)) { - window && window.disconnect(signals.get(TilingSignals.RAISE)); - signals.set(TilingSignals.RAISE, 0); - } - - if (signals.get(TilingSignals.WS_CHANGED)) { - window && window.disconnect(signals.get(TilingSignals.WS_CHANGED)); - signals.set(TilingSignals.WS_CHANGED, 0); - } - - if (signals.get(TilingSignals.UNMANAGING)) { - window && window.disconnect(signals.get(TilingSignals.UNMANAGING)); - signals.set(TilingSignals.UNMANAGING, 0); - } - - if (!this._tileGroups.has(windowId)) - return; - - // Delete window's tileGroup - this._tileGroups.delete(windowId); - // Delete window from other windows' tileGroup - this._tileGroups.forEach(tileGroup => { - const idx = tileGroup.indexOf(windowId); - idx !== -1 && tileGroup.splice(idx, 1); - }); - } - - /** - * @param {Meta.Window} window a Meta.Window. - * @returns {Meta.Window[]} an array of Meta.Windows, which are in `window`'s - * tile group (including the `window` itself). - */ - static getTileGroupFor(window) { - const tileGroup = this._tileGroups.get(window.get_id()); - if (!tileGroup) - return []; - - return this._getAllWindows().filter(w => tileGroup.includes(w.get_id())); - } - - /** - * Gets the top most tiled window group; that means they complement each - * other and don't intersect. This may differ from the TileGroupManager's - * *tracked* tile groups since floating windows may overlap some tiled - * windows *at the moment* when this function is called. - * - * @param {boolean} [skipTopWindow=true] whether we ignore the focused window - * in the active search for the top tile group. The focused window may - * still be part of the returned array if it is part of another high- - * stacked window's tile group. This is mainly only useful, if the - * focused window isn't tiled (for example when dnd-ing a window). - * @param {number} [monitor=null] get the group for the monitor number. - * @returns {Meta.Windows[]} an array of tiled Meta.Windows. - */ - static getTopTileGroup({ skipTopWindow = false, monitor = null } = {}) { - // 'Raise Tile Group' setting is enabled so we just return the tracked - // tile group. Same thing for the setting 'Disable Tile Groups' because - // it's implemented by just making the tile groups consist of single - // windows (the tiled window itself). - if (Settings.getBoolean(Settings.RAISE_TILE_GROUPS) || - Settings.getBoolean(Settings.DISABLE_TILE_GROUPS) - ) { - const openWindows = this.getWindows(); - if (!openWindows.length) - return []; - - if (skipTopWindow) { - // the focused window isn't necessarily the top window due to always - // on top windows. - const idx = openWindows.indexOf(global.display.focus_window); - idx !== -1 && openWindows.splice(idx, 1); - } - - const ignoredWindows = []; - const mon = monitor ?? - global.display.focus_window?.get_monitor() ?? - openWindows[0].get_monitor(); - - for (const window of openWindows) { - if (window.get_monitor() !== mon) - continue; - - // Ignore non-tiled windows, which are always-on-top, for the - // calculation since they are probably some utility apps etc. - if (window.is_above() && !window.isTiled) - continue; - - // Find the first not overlapped tile group, if it exists - if (window.isTiled) { - const overlapsIgnoredWindow = ignoredWindows.some(w => { - const rect = w.tiledRect ?? new Rect(w.get_frame_rect()); - return rect.overlap(window.tiledRect); - }); - - if (overlapsIgnoredWindow) - ignoredWindows.push(window); - else - return this.getTileGroupFor(window); - } else { - ignoredWindows.push(window); - } - } - - return []; - - // 'Raise Tile Group' setting is disabled so we get thetop most - // non-overlapped/ing tiled windows ignoring the tile groups. - } else { - return this._getTopTiledWindows({ skipTopWindow, monitor }); - } - } - - /** - * Gets the free screen space (1 big Rect). If the free screen space - * is ambiguous that means it consists of multiple (unaligned) rectangles - * (for ex.: 2 diagonally opposing quarters). In that case we return null. - * - * @param {Rect[]} rectList an array of Rects, which occupy the screen. - * @param {number|null} [monitorNr] useful for the grace period during dnd. - * Defaults to pointer monitor. - * @returns {Rect|null} a Rect, which represent the free screen space. - */ - static getFreeScreen(rectList, monitorNr = null) { - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = monitorNr ?? global.display.get_current_monitor(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - const freeScreenRects = workArea.minus(rectList); - if (!freeScreenRects.length) - return null; - - // Create the union of all freeScreenRects and calculate the sum - // of their areas. If the area of the union-rect equals the area - // of the individual rects, the individual rects align properly. - const startRect = new Rect(freeScreenRects[0].x, freeScreenRects[0].y, 0, 0); - const { checkSum, combinedRect } = freeScreenRects.reduce((result, rect) => { - result.checkSum += rect.area; - result.combinedRect = result.combinedRect.union(rect); - return result; - }, { checkSum: 0, combinedRect: startRect }); - - if (combinedRect.area !== checkSum) - return null; - - // Random min. size requirement - if (combinedRect.width < 250 || combinedRect.height < 250) - return null; - - return combinedRect; - } - - /** - * Gets the best available free screen rect. If a `currRect` is passed, - * instead this will return an expanded copy of that rect filling all - * the available space around it. - * - * @param {Rect[]} rectList an array of Rects, which occupy the screen. - * Like usual, they shouldn't overlap each other. - * @param {Rect} [currRect=null] a Rect, which may be expanded. - * @param {Orientation} [orientation=null] The orientation we want to expand - * `currRect` into. If `null`, expand in both orientations. - * @param {Rect} [monitor=null] defaults to pointer monitor. - * @returns {Rect} a new Rect. - */ - static getBestFreeRect(rectList, { currRect = null, orientation = null, monitorNr = null } = {}) { - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = monitorNr ?? global.display.get_current_monitor(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - const freeRects = workArea.minus(rectList); - if (!freeRects.length) - return currRect ?? new Rect(workArea); - - // Try to expand the currRect to fill the rest of the space - // that is available around it. - if (currRect) { - const isVert = (orientation ?? Orientation.V) === Orientation.V; - const [xpndPos1, xpndPos2] = isVert ? ['y', 'y2'] : ['x', 'x2']; - const [unxpndPos1, unxpndPos2] = isVert ? ['x', 'x2'] : ['y', 'y2']; - - // Filter the rects to only keep the ones directly bordering the - // currRect and sort the array so that the free rects are ordered - // from the left to the right or from the top to the bottom. See - // below for the reasoning. - const borderingRects = freeRects.filter(r => { - const axis1 = currRect[xpndPos1] === r[xpndPos2] || currRect[xpndPos2] === r[xpndPos1]; - const axis2 = isVert ? currRect.horizOverlap(r) : currRect.vertOverlap(r); - return axis1 && axis2; - }).sort((a, b) => a[unxpndPos1] - b[unxpndPos1]); - - // Separate the rects into the ones that come before (left / top) - // or after (right / bottom) the current rect. - const { before, after } = borderingRects.reduce((result, r) => { - if (currRect[xpndPos1] === r[xpndPos2]) - result.before.push(r); - else if (currRect[xpndPos2] === r[xpndPos1]) - result.after.push(r); - - return result; - }, { before: [], after: [] }); - - // If we want to check whether the current rect can expand on a certain - // side (let's say we expand the height), we need to check the *other* - // (unexpanded) side. So whether the current rect is bordering the free - // screen rects along its *entire width*. We do this by 'union-ing' the - // free screen rects along the relevant side (our ex.: width). For this - // reason we needed to sort the free rects in ascending order before - // to make sure they overlap before trying to 'union' them. After the - // union-ing, we just check, if the union-ed rect contains the current - // rects unexpanded side. - - // Orientation doesn't matter here since we are always comparing sides - // of the same orientation. So just make the side always horizontal. - const makeSide = (startPoint, endPoint) => new Mtk.Rectangle({ - x: startPoint, - width: endPoint - startPoint, - height: 1 - }); - const freeRectsContainCurrRectSide = rects => { - const currRectSide = makeSide(currRect[unxpndPos1], currRect[unxpndPos2]); - const linkedSides = rects.reduce((linked, r) => { - const side = makeSide(r[unxpndPos1], r[unxpndPos2]); - return linked.overlap(side) ? linked.union(side) : linked; - }, makeSide(rects[0][unxpndPos1], rects[0][unxpndPos2])); - - return linkedSides.contains_rect(currRectSide); - }; - - const newRect = currRect.copy(); - - // Expand to the left / top. - if (before.length) { - if (freeRectsContainCurrRectSide(before)) { - const expandStartTo = before.reduce((currSize, rect) => { - return Math.max(currSize, rect[xpndPos1]); - }, before[0][xpndPos1]); - - newRect[xpndPos2] += newRect[xpndPos1] - expandStartTo; - newRect[xpndPos1] = expandStartTo; - } - } - - // Expand to the right / bottom. - if (after.length) { - if (freeRectsContainCurrRectSide(after)) { - const expandEndTo = after.reduce((currSize, rect) => { - return Math.min(currSize, rect[xpndPos2]); - }, after[0][xpndPos2]); - - newRect[xpndPos2] = expandEndTo; - } - } - - if (!orientation) { - // if orientation is null, we expanded vertically. Now we want - // to expand horizontally as well. - rectList = [...rectList]; - const currRectIdx = rectList.findIndex(r => r.equal(currRect)); - rectList.splice(currRectIdx, 1); - rectList.push(newRect); - return newRect.union( - this.getBestFreeRect(rectList, { - currRect: newRect, - orientation: Orientation.H, - monitorNr: monitor - })); - } else { - return newRect; - } - - // No currRect was passed, so we just choose the single biggest free rect - // and expand it using this function. This is a naive approach and doesn't - // guarantee that we get the best combination of free screen rects... but - // it should be good enough. - } else { - const biggestSingle = freeRects.reduce((currBiggest, rect) => { - return currBiggest.area >= rect.area ? currBiggest : rect; - }); - rectList.push(biggestSingle); - - return this.getBestFreeRect(rectList, { currRect: biggestSingle }); - } - } - - /** - * Gets the nearest Meta.Window in the direction of `dir`. - * - * @param {Meta.Windows} currWindow the Meta.Window that the search starts - * from. - * @param {Meta.Windows[]} windows an array of the available Meta.Windows. - * It may contain the current window itself. The windows shouldn't - * overlap each other. - * @param {Direction} dir the direction that is look into. - * @param {boolean} [wrap=true] whether we wrap around, - * if there is no Meta.Window in the direction of `dir`. - * @returns {Meta.Window|null} the nearest Meta.Window. - */ - static getNearestWindow(currWindow, windows, dir, wrap = true) { - const getRect = w => w.tiledRect ?? new Rect(w.get_frame_rect()); - const rects = windows.map(w => getRect(w)); - const nearestRect = getRect(currWindow).getNeighbor(dir, rects, wrap); - if (!nearestRect) - return null; - - return windows.find(w => getRect(w).equal(nearestRect)); - } - - /** - * Gets the rectangle for special positions adapted to the surrounding - * rectangles. The position is determined by `shortcut` but this function - * isn't limited to just keyboard shortcuts. This is also used when - * dnd-ing a window. - * - * Examples: Shortcuts.LEFT gets the left-most rectangle with the height - * of the workArea. Shortcuts.BOTTOM_LEFT gets the rectangle touching the - * bottom left screen corner etc... If there is no other rect to adapt to - * we default to half the workArea. - * - * @param {Shortcuts} shortcut the side / quarter to get the tile rect for. - * @param {Rect} workArea the workArea. - * @param {number} [monitor=null] the monitor number we want to get the - * rect for. This may not always be the current monitor. It is only - * used to implement the 'grace period' to enable quickly tiling a - * window using the screen edges even if there is another monitor - * at that edge. - * @returns a Rect. - */ - static getTileFor(shortcut, workArea, monitor = null) { - // Don't try to adapt a tile rect - if (Settings.getBoolean(Settings.DISABLE_TILE_GROUPS)) - return this.getDefaultTileFor(shortcut, workArea); - - const topTileGroup = this.getTopTileGroup({ skipTopWindow: true, monitor }); - // getTileFor is used to get the adaptive tiles for dnd & tiling keyboard - // shortcuts. That's why the top most window needs to be ignored when - // calculating the new tile rect. The top most window is already ignored - // for dnd in the getTopTileGroup() call. While the top most window will - // be ignored for the active search in getTopTileGroup, it may still be - // part of the returned array if it's part of another high-stackeing - // window's tile group. - const idx = topTileGroup.indexOf(global.display.focus_window); - idx !== -1 && topTileGroup.splice(idx, 1); - const favLayout = Util.getFavoriteLayout(monitor); - const useFavLayout = favLayout.length && Settings.getBoolean(Settings.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT); - const twRects = useFavLayout && favLayout || topTileGroup.map(w => w.tiledRect); - - if (!twRects.length) - return this.getDefaultTileFor(shortcut, workArea); - - // Return the adapted rect only if it doesn't overlap an existing tile. - // Ignore an overlap, if a fav layout is used since we always prefer the - // user set layout in that case. - const getTile = rect => { - if (useFavLayout) - return rect; - - const overlapsTiles = twRects.some(r => r.overlap(rect)); - return overlapsTiles ? this.getDefaultTileFor(shortcut, workArea) : rect; - }; - - const screenRects = twRects.concat(workArea.minus(twRects)); - switch (shortcut) { - case Shortcuts.MAXIMIZE: { - return workArea.copy(); - } case Shortcuts.LEFT: { - const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); - const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); - const result = new Rect(workArea.x, workArea.y, width, workArea.height); - return getTile(result); - } case Shortcuts.RIGHT: { - const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); - const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); - const result = new Rect(workArea.x2 - width, workArea.y, width, workArea.height); - return getTile(result); - } case Shortcuts.TOP: { - const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); - const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x, workArea.y, workArea.width, height); - return getTile(result); - } case Shortcuts.BOTTOM: { - const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); - const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x, workArea.y2 - height, workArea.width, height); - return getTile(result); - } case Shortcuts.TOP_LEFT: { - const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); - const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); - const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); - const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x, workArea.y, width, height); - return getTile(result); - } case Shortcuts.TOP_RIGHT: { - const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); - const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); - const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); - const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x2 - width, workArea.y, width, height); - return getTile(result); - } case Shortcuts.BOTTOM_LEFT: { - const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); - const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); - const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); - const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x, workArea.y2 - height, width, height); - return getTile(result); - } case Shortcuts.BOTTOM_RIGHT: { - const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); - const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); - const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); - const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); - const result = new Rect(workArea.x2 - width, workArea.y2 - height, width, height); - return getTile(result); - } - } - } - - /** - * @param {Shortcuts} shortcut determines, which half/quarter to get the tile for - * @param {Rect} workArea - * @returns - */ - static getDefaultTileFor(shortcut, workArea) { - switch (shortcut) { - case Shortcuts.MAXIMIZE: - return workArea.copy(); - case Shortcuts.LEFT: - case Shortcuts.LEFT_IGNORE_TA: - return workArea.getUnitAt(0, workArea.width / 2, Orientation.V); - case Shortcuts.RIGHT: - case Shortcuts.RIGHT_IGNORE_TA: - return workArea.getUnitAt(1, workArea.width / 2, Orientation.V); - case Shortcuts.TOP: - case Shortcuts.TOP_IGNORE_TA: - return workArea.getUnitAt(0, workArea.height / 2, Orientation.H); - case Shortcuts.BOTTOM: - case Shortcuts.BOTTOM_IGNORE_TA: - return workArea.getUnitAt(1, workArea.height / 2, Orientation.H); - case Shortcuts.TOP_LEFT: - case Shortcuts.TOP_LEFT_IGNORE_TA: - return workArea.getUnitAt(0, workArea.width / 2, Orientation.V).getUnitAt(0, workArea.height / 2, Orientation.H); - case Shortcuts.TOP_RIGHT: - case Shortcuts.TOP_RIGHT_IGNORE_TA: - return workArea.getUnitAt(1, workArea.width / 2, Orientation.V).getUnitAt(0, workArea.height / 2, Orientation.H); - case Shortcuts.BOTTOM_LEFT: - case Shortcuts.BOTTOM_LEFT_IGNORE_TA: - return workArea.getUnitAt(0, workArea.width / 2, Orientation.V).getUnitAt(1, workArea.height / 2, Orientation.H); - case Shortcuts.BOTTOM_RIGHT: - case Shortcuts.BOTTOM_RIGHT_IGNORE_TA: - return workArea.getUnitAt(1, workArea.width / 2, Orientation.V).getUnitAt(1, workArea.height / 2, Orientation.H); - } - } - - /** - * Opens the Tiling Popup, if there is unambiguous free screen space, - * and offer to tile an open window to that spot. - */ - static async tryOpeningTilingPopup() { - if (!Settings.getBoolean(Settings.ENABLE_TILING_POPUP)) - return; - - const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); - const openWindows = this.getWindows(allWs); - const topTileGroup = this.getTopTileGroup(); - topTileGroup.forEach(w => openWindows.splice(openWindows.indexOf(w), 1)); - if (!openWindows.length) - return; - - const tRects = topTileGroup.map(w => w.tiledRect); - const monitor = topTileGroup[0]?.get_monitor(); // for the grace period - const freeSpace = this.getFreeScreen(tRects, monitor); - if (!freeSpace) - return; - - const TilingPopup = await import('./tilingPopup.js'); - const popup = new TilingPopup.TilingSwitcherPopup(openWindows, freeSpace); - if (!popup.show(topTileGroup)) - popup.destroy(); - } - - /** - * Tiles or untiles a window based on its current tiling state. - * - * @param {Meta.Window} window a Meta.Window. - * @param {Rect} rect the Rect the `window` tiles to or untiles from. - */ - static toggleTiling(window, rect, params = {}) { - const workArea = window.get_work_area_current_monitor(); - const equalsWA = rect.equal(workArea); - const equalsTile = window.tiledRect && rect.equal(window.tiledRect); - if (window.isTiled && equalsTile || this.isMaximized(window) && equalsWA) - this.untile(window, params); - else - this.tile(window, rect, params); - } - - /** - * Tries to open an app on a tiling state (in a very dumb way...). - * - * @param {Shell.App} app the Shell.App to open and tile. - * @param {Rect} rect the Rect to tile to. - * @param {boolean} [openTilingPopup=false] allow the Tiling Popup to - * appear, if there is free screen space after the `app` was tiled. - */ - static openAppTiled(app, rect, openTilingPopup = false) { - if (!app?.can_open_new_window()) - return; - - let createId = global.display.connect('window-created', (src, window) => { - const wActor = window.get_compositor_private(); - let firstFrameId = wActor?.connect('first-frame', () => { - wActor.disconnect(firstFrameId); - firstFrameId = 0; - - const winTracker = Shell.WindowTracker.get_default(); - const openedWindowApp = winTracker.get_window_app(window); - // Check, if the created window is from the app and if it allows - // to be moved and resized because, for example, Steam uses a - // WindowType.Normal window for their loading screen, which we - // don't want to trigger the tiling for. - if (createId && openedWindowApp && openedWindowApp === app && - (window.allows_resize() && window.allows_move() || window.get_maximized()) - ) { - global.display.disconnect(createId); - createId = 0; - this.tile(window, rect, { openTilingPopup, skipAnim: true }); - } - }); - - // Don't immediately disconnect the signal in case the launched - // window doesn't match the original app. It may be a loading screen - // or the user started an app in between etc... but in case the checks/ - // signals above fail disconnect the signals after 1 min at the latest - this._openAppTiledTimerId && GLib.Source.remove(this._openAppTiledTimerId); - this._openAppTiledTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 60000, () => { - createId && global.display.disconnect(createId); - createId = 0; - firstFrameId && wActor.disconnect(firstFrameId); - firstFrameId = 0; - this._openAppTiledTimerId = null; - return GLib.SOURCE_REMOVE; - }); - }); - - app.open_new_window(-1); - } - - /** - * Gets the top windows, which are supposed to be in a tile group. That - * means windows, which are tiled, and don't overlap each other. - */ - static _getWindowsForBuildingTileGroup(monitor = null) { - const openWindows = this.getWindows(); - if (!openWindows.length) - return []; - - const ignoredWindows = []; - const result = []; - const mon = monitor ?? - global.display.focus_window?.get_monitor() ?? - openWindows[0].get_monitor(); - - for (const window of openWindows) { - if (window.get_monitor() !== mon) - continue; - - if (window.is_above() && !window.isTiled) - continue; - - if (window.isTiled) { - // Window was already checked as part of another's tileGroup. - if (ignoredWindows.includes(window) || result.includes(window)) - continue; - - // Check for the other windows in the tile group as well regardless - // of the 'raise tile group' setting so that once the setting is - // enabled the tile groups are already set properly. - - const tileGroup = this.getTileGroupFor(window); - - // This means `window` is the window that was just tiled and - // thus has no tileGroup set at this point yet. - if (!tileGroup.length) { - result.push(window); - continue; - } - - const tileGroupOverlaps = tileGroup.some(w => - result.some(r => r.tiledRect.overlap(w.tiledRect)) || - ignoredWindows.some(r => (r.tiledRect ?? new Rect(r.get_frame_rect())).overlap(w.tiledRect))); - - tileGroupOverlaps - ? tileGroup.forEach(w => ignoredWindows.push(w)) - : tileGroup.forEach(w => result.push(w)); - } else { - // The window is maximized, so all windows below it can't belong - // to this group anymore. - if (this.isMaximized(window)) - break; - - ignoredWindows.push(window); - } - } - - return result; - } - - /** - * Gets the top most non-overlapped/ing tiled windows ignoring - * the stacking order and tile groups. - * - * @param {{boolean, number}} param1 - */ - static _getTopTiledWindows({ skipTopWindow = false, monitor = null } = {}) { - const openWindows = this.getWindows(); - if (!openWindows.length) - return []; - - if (skipTopWindow) { - // the focused window isn't necessarily the top window due to always - // on top windows. - const idx = openWindows.indexOf(global.display.focus_window); - idx !== -1 && openWindows.splice(idx, 1); - } - - const topTiledWindows = []; - const ignoredWindows = []; - const mon = monitor ?? - global.display.focus_window?.get_monitor() ?? - openWindows[0].get_monitor(); - - for (const window of openWindows) { - if (window.get_monitor() !== mon) - continue; - - if (window.is_above() && !window.isTiled) - continue; - - if (window.isTiled) { - const wRect = window.tiledRect; - - // If a ignored window in a higher stack order overlaps the - // currently tested tiled window, the currently tested tiled - // window isn't part of the top tile group. - const overlapsIgnoredWindow = ignoredWindows.some(w => { - const rect = w.tiledRect ?? new Rect(w.get_frame_rect()); - return rect.overlap(wRect); - }); - // Same applies for already grouped windows - const overlapsTopTiledWindows = topTiledWindows.some(w => w.tiledRect.overlap(wRect)); - - overlapsIgnoredWindow || overlapsTopTiledWindows - ? ignoredWindows.push(window) - : topTiledWindows.push(window); - } else { - // The window is maximized, so all windows below it can't belong - // to this group anymore. - if (this.isMaximized(window)) - break; - - ignoredWindows.push(window); - } - } - - return topTiledWindows; - } - - /** - * Blocks all tiling signals for a window. - * - * @param {Meta.Window} window - */ - static _blockTilingSignalsFor(window) { - const signals = this._signals.getSignalsFor(window.get_id()); - const blockedSignals = [TilingSignals.RAISE, TilingSignals.WS_CHANGED, TilingSignals.UNMANAGING]; - blockedSignals.forEach(s => { - const id = signals.get(s); - id && window.block_signal_handler(id); - }); - } - - /** - * Unblocks all tiling signals for a window. - * Should only be called after _blockTilingSignalsFor(). - * - * @param {Meta.Window} window - */ - static _unblockTilingSignalsFor(window) { - const signals = this._signals.getSignalsFor(window.get_id()); - const blockedSignals = [TilingSignals.RAISE, TilingSignals.WS_CHANGED, TilingSignals.UNMANAGING]; - blockedSignals.forEach(s => { - const id = signals.get(s); - id && window.unblock_signal_handler(id); - }); - } - - /** - * Updates the signals after maximizing a window with gaps. - * - * @param {Meta.Window} window - */ - static _updateGappedMaxWindowSignals(window) { - const wId = window.get_id(); - const signals = this._signals.getSignalsFor(wId); - - // Refresh 'unmanaging' signal - const unmanagingSignal = signals.get(TilingSignals.UNMANAGING); - unmanagingSignal && window.disconnect(unmanagingSignal); - - const umId = window.connect('unmanaging', w => { - this.clearTilingProps(window.get_id()); - this._unmanagingWindows.push(w.get_stable_sequence()); - }); - signals.set(TilingSignals.UNMANAGING, umId); - - // Refresh 'workspace-changed' signal - const wsId = window.connect('workspace-changed', () => this._onWindowWorkspaceChanged(window)); - this._signals.getSignalsFor(wId).set(TilingSignals.WS_CHANGED, wsId); - } - - /** - * @returns {Meta.Window[]} an array of *all* windows - * (and not just the ones relevant to altTab) - */ - static _getAllWindows() { - return global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null); - } - - /** - * Gets the window matching a window id - * - * @param {number} id - * @returns {Meta.Window} - */ - static _getWindow(id) { - return this._getAllWindows().find(w => w.get_id() === id); - } - - /** - * A window's workspace-changed signal is used to untile it when the user - * changes its workspace. However, dynamic workspaces *may* also trigger a - * ws-changed signal. So listen to the workspace-added/removed signals and - * 'ignore' the next ws-changed signal. A ws addition/removal doesn't guarantuee - * a ws-changed signal (e. g. the workspace is at the end), so reset after - * a short timer. - */ - static _onWorkspaceAdded() { - this._ignoreWsChange = true; - this._wsAddedTimer && GLib.Source.remove(this._wsAddedTimer); - this._wsAddedTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, () => { - this._ignoreWsChange = false; - this._wsAddedTimer = null; - return GLib.SOURCE_REMOVE; - }); - } - - /** - * A window's workspace-changed signal is used to untile it when the user - * changes its workspace. However, dynamic workspaces *may* also trigger a - * ws-changed signal. So listen to the workspace-added/removed signals and - * 'ignore' the next ws-changed signal. A ws addition/removal doesn't guarantuee - * a ws-changed signal (e. g. the workspace is at the end), so reset after - * a short timer. - */ - static _onWorkspaceRemoved() { - this._ignoreWsChange = true; - this._wsRemovedTimer && GLib.Source.remove(this._wsRemovedTimer); - this._wsRemovedTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, () => { - this._ignoreWsChange = false; - this._wsRemovedTimer = null; - return GLib.SOURCE_REMOVE; - }); - } - - /** - * This is only called for tiled and maximized (with gaps) windows. - * Untile tiled windows. Re-tile maximized windows to fit the whole workArea - * since a monitor change will also trigger a workspace-change signal. - * Previously, we tried to adapt the tiled window's size to the new monitor - * but that is probably too unpredictable. First, it may introduce rounding - * errors when moving multiple windows of the same tileGroup and second (and - * more importantly) the behavior with regards to tileGroups isn't clear... - * Should the entire tileGroup move, if 1 tiled window is moved? If not, - * there should probably be a way to just detach 1 window from a group. What - * happens on the new monitor, if 1 window is moved? Should it create a new - * tileGroup? Should it try to integrate into existing tileGroups on that - * monitor etc... there are too many open questions. Instead just untile - * and leave it up to the user to re-tile a window. - * - * @param {Meta.Window} window - */ - static _onWindowWorkspaceChanged(window) { - // Closing a window triggers a ws-changed signal, which may lead to a - // crash, if we try to operate on it any further. So we listen to the - // 'unmanaging'-signal to see, if there is a 'true workspace change' - // or whether the window was just closed - if (this._unmanagingWindows.includes(window.get_stable_sequence())) - return; - - if (this._ignoreWsChange) - return; - - if (this.isMaximized(window)) { - const wA = window.get_work_area_for_monitor(window.get_monitor()); - const workArea = new Rect(wA); - if (workArea.equal(window.tiledRect)) - return; - - this.tile(window, workArea, { openTilingPopup: false, skipAnim: true }); - } else if (window.isTiled) { - this.untile(window, { restoreFullPos: false, clampToWorkspace: true, skipAnim: Main.overview.visible }); - } - } -} - -/** - * This is instanced by the 'TilingWindowManager'. It implements the tiling - * signals and tracks the signal( id)s, which are relevant for tiling: - * Raise: for group raising. - * Ws-changed: for untiling a tiled window after its ws changed. - * Unmanaging: to remove unmanaging tiled windows from the other tileGroups. - */ -const TilingSignals = GObject.registerClass({ - Signals: { - 'window-tiled': { param_types: [Meta.Window.$gtype] }, - 'window-untiled': { param_types: [Meta.Window.$gtype] } - } -}, class TilingSignals extends Clutter.Actor { - // Relevant 'signal types' (sorta used as an enum / key for the signal map). - // Tiled windows use all 3 signals; maximized-with-gaps windows only use the - // workspace-changed and unmanaging signal. - static RAISE = 'RAISE'; - static WS_CHANGED = 'WS_CHANGED'; - static UNMANAGING = 'UNMANAGING'; - - _init() { - super._init(); - - // { windowId1: { RAISE: signalId1, WS_CHANGED: signalId2, UNMANAGING: signalId3 }, ... } - this._ids = new Map(); - } - - destroy() { - // Disconnect remaining signals - const allWindows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null); - this._ids.forEach((signals, windowId) => { - const window = allWindows.find(w => w.get_id() === windowId); - window && signals.forEach(s => s && window.disconnect(s)); - }); - - super.destroy(); - } - - /** - * Gets the signal ids for the raise, ws-changed and unmanaging signals - * for a specific window - * - * @param {number} windowId Meta.Window's id - * @returns {Map} the tiling signal ids for the window (id) - * with a 'signal type' as the keys - */ - getSignalsFor(windowId) { - let ret = this._ids.get(windowId); - if (!ret) { - ret = new Map(); - this._ids.set(windowId, ret); - } - - return ret; - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/utility.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/utility.js deleted file mode 100644 index 2de6665..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/extension/utility.js +++ /dev/null @@ -1,789 +0,0 @@ -import { Clutter, Gio, GLib, Mtk, St } from '../dependencies/gi.js'; -import { Main } from '../dependencies/shell.js'; - -import { Direction, Orientation, Settings } from '../common.js'; - -/** - * Library of commonly used functions for the extension.js' files - * (and *not* the prefs files) - */ - -export class Util { - /** - * Performs an approximate equality check. There will be times when - * there will be inaccuracies. For example, the user may enable window - * gaps and resize 2 tiled windows and try to line them up manually. - * But since the gaps are implemented with this extension, there will - * be no window snapping. So the windows won't be aligned pixel - * perfectly... in that case we first check approximately and correct - * the inaccuracies afterwards. - * - * @param {number} value - * @param {number} value2 - * @param {number} [margin=4] - * @returns {boolean} whether the values are approximately equal. - */ - static equal(value, value2, margin = 4) { - return Math.abs(value - value2) <= margin; - } - - /** - * @param {{x, y}} pointA - * @param {{x, y}} pointB - * @returns {number} the distance between `pointA` and `pointB`, - */ - static getDistance(pointA, pointB) { - const diffX = pointA.x - pointB.x; - const diffY = pointA.y - pointB.y; - return Math.sqrt(diffX * diffX + diffY * diffY); - } - - /** - * @param {number} keyVal - * @param {Direction} direction - * @returns {boolean} whether the `keyVal` is considered to be in the - * direction of `direction`. - */ - static isDirection(keyVal, direction) { - switch (direction) { - case Direction.N: - return keyVal === Clutter.KEY_Up || - keyVal === Clutter.KEY_w || keyVal === Clutter.KEY_W || - keyVal === Clutter.KEY_k || keyVal === Clutter.KEY_K; - - case Direction.S: - return keyVal === Clutter.KEY_Down || - keyVal === Clutter.KEY_s || keyVal === Clutter.KEY_S || - keyVal === Clutter.KEY_j || keyVal === Clutter.KEY_J; - - case Direction.W: - return keyVal === Clutter.KEY_Left || - keyVal === Clutter.KEY_a || keyVal === Clutter.KEY_A || - keyVal === Clutter.KEY_h || keyVal === Clutter.KEY_H; - - case Direction.E: - return keyVal === Clutter.KEY_Right || - keyVal === Clutter.KEY_d || keyVal === Clutter.KEY_D || - keyVal === Clutter.KEY_l || keyVal === Clutter.KEY_L; - } - - return false; - } - - /** - * @param {number} keyVal - * @returns {Direction} - */ - static getDirection(keyVal) { - if (this.isDirection(keyVal, Direction.N)) - return Direction.N; - else if (this.isDirection(keyVal, Direction.S)) - return Direction.S; - else if (this.isDirection(keyVal, Direction.W)) - return Direction.W; - else if (this.isDirection(keyVal, Direction.E)) - return Direction.E; - else - return null; - } - - /** - * Get the window or screen gaps scaled to the monitor scale. - * - * @param {String} settingsKey the key for the gap - * @param {number} monitor the number of the monitor to scale the gap to - * @returns {number} the scaled gap as a even number since the window gap - * will be divided by 2. - */ - static getScaledGap(settingsKey, monitor) { - const gap = Settings.getInt(settingsKey); - const scaledGap = gap * global.display.get_monitor_scale(monitor); - return scaledGap % 2 === 0 ? scaledGap : scaledGap + 1; - } - - static useIndividualGaps(monitor) { - // Prefer individual gaps over the single one - const screenTopGap = this.getScaledGap(Settings.SCREEN_TOP_GAP, monitor); - const screenLeftGap = this.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor); - const screenRightGap = this.getScaledGap(Settings.SCREEN_RIGHT_GAP, monitor); - const screenBottomGap = this.getScaledGap(Settings.SCREEN_BOTTOM_GAP, monitor); - return screenTopGap || screenLeftGap || screenRightGap || screenBottomGap; - } - - /** - * @param {number} modMask a Clutter.ModifierType. - * @returns whether the current event the modifier at `modMask`. - */ - static isModPressed(modMask) { - return global.get_pointer()[2] & modMask; - } - - /** - * @returns {Layout[]} the layouts - */ - static getLayouts() { - const userDir = GLib.get_user_config_dir(); - const pathArr = [userDir, '/tiling-assistant/layouts.json']; - const path = GLib.build_filenamev(pathArr); - const file = Gio.File.new_for_path(path); - if (!file.query_exists(null)) - return []; - - const [success, contents] = file.load_contents(null); - if (!success || !contents.length) - return []; - - return JSON.parse(new TextDecoder().decode(contents)); - } - - /** - * @param {number|null} monitorNr determines which monitor the layout scales - * to. Sometimes we want the monitor of the pointer (when using dnd) and - * sometimes not (when using layouts with the keyboard shortcuts). - * @returns {Rect[]} - */ - static getFavoriteLayout(monitorNr = null) { - // I don't know when the layout may have changed on the disk(?), - // so always get it anew. - const monitor = monitorNr ?? global.display.get_current_monitor(); - const favoriteLayout = []; - const layouts = this.getLayouts(); - const layout = layouts?.[Settings.getStrv(Settings.FAVORITE_LAYOUTS)[monitor]]; - - if (!layout) - return []; - - const activeWs = global.workspace_manager.get_active_workspace(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - - // Scale the rect's ratios to the workArea. Try to align the rects to - // each other and the workArea to workaround possible rounding errors - // due to the scaling. - layout._items.forEach(({ rect: rectRatios }, idx) => { - const rect = new Rect( - workArea.x + Math.floor(rectRatios.x * workArea.width), - workArea.y + Math.floor(rectRatios.y * workArea.height), - Math.ceil(rectRatios.width * workArea.width), - Math.ceil(rectRatios.height * workArea.height) - ); - favoriteLayout.push(rect); - - for (let i = 0; i < idx; i++) - rect.tryAlignWith(favoriteLayout[i]); - }); - - favoriteLayout.forEach(rect => rect.tryAlignWith(workArea)); - return favoriteLayout; - } - - /** - * Shows the tiled rects of the top tile group. - * - * @returns {St.Widget[]} an array of St.Widgets to indicate the tiled rects. - */ - static async ___debugShowTiledRects() { - const twm = (await import('./tilingWindowManager.js')).TilingWindowManager; - const topTileGroup = twm.getTopTileGroup(); - if (!topTileGroup.length) { - Main.notify('Tiling Assistant', 'No tiled windows / tiled rects.'); - return null; - } - - const indicators = []; - topTileGroup.forEach(w => { - const indicator = new St.Widget({ - style_class: 'tile-preview', - opacity: 160, - x: w.tiledRect.x, - y: w.tiledRect.y, - width: w.tiledRect.width, - height: w.tiledRect.height - }); - Main.uiGroup.add_child(indicator); - indicators.push(indicator); - }); - - return indicators; - } - - /** - * Shows the free screen rects based on the top tile group. - * - * @returns {St.Widget[]} an array of St.Widgets to indicate the free - * screen rects. - */ - static async ___debugShowFreeScreenRects() { - const activeWs = global.workspace_manager.get_active_workspace(); - const monitor = global.display.get_current_monitor(); - const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); - const twm = (await import('./tilingWindowManager.js')).TilingWindowManager; - const topTileGroup = twm.getTopTileGroup(); - const tRects = topTileGroup.map(w => w.tiledRect); - const freeScreenSpace = twm.getFreeScreen(tRects); - const rects = freeScreenSpace ? [freeScreenSpace] : workArea.minus(tRects); - if (!rects.length) { - Main.notify('Tiling Assistant', 'No free screen rects to show.'); - return null; - } - - const indicators = []; - rects.forEach(rect => { - const indicator = new St.Widget({ - style_class: 'tile-preview', - x: rect.x, - y: rect.y, - width: rect.width, - height: rect.height - }); - Main.uiGroup.add_child(indicator); - indicators.push(indicator); - }); - - return indicators.length ? indicators : null; - } - - /** - * Print the tile groups to the logs. - */ - static async __debugPrintTileGroups() { - log('--- Tiling Assistant: Start ---'); - const twm = await import('./tilingWindowManager.js'); - const openWindows = twm.getWindows(); - openWindows.forEach(w => { - if (!w.isTiled) - return; - - log(`Tile group for: ${w.get_wm_class()}`); - const tileGroup = twm.getTileGroupFor(w); - tileGroup.forEach(tw => log(tw.get_wm_class())); - log('---'); - }); - log('--- Tiling Assistant: End ---'); - } -} - -/** - * Wrapper for Mtk.Rectangle to add some more functions. - */ -export class Rect { - /** - * @param {...any} params No parameters, 1 Mtk.Rectangle or the x, y, - * width and height values should be passed to the constructor. - */ - constructor(...params) { - this._rect = new Mtk.Rectangle(); - - switch (params.length) { - case 0: - break; - - case 1: - this._rect.x = params[0].x; - this._rect.y = params[0].y; - this._rect.width = params[0].width; - this._rect.height = params[0].height; - break; - - case 4: - this._rect.x = params[0]; - this._rect.y = params[1]; - this._rect.width = params[2]; - this._rect.height = params[3]; - break; - - default: - log('Tiling Assistant: Invalid param count for Rect constructor!'); - } - } - - /** - * Gets a new rectangle where the screen and window gaps were - * added/subbed to/from `this`. - * - * @param {Rect} rect a tiled Rect - * @param {number} monitor the number of the monitor to scale the gap to - * @returns {Rect} the rectangle after the gaps were taken into account - */ - addGaps(workArea, monitor) { - const screenTopGap = Util.getScaledGap(Settings.SCREEN_TOP_GAP, monitor); - const screenLeftGap = Util.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor); - const screenRightGap = Util.getScaledGap(Settings.SCREEN_RIGHT_GAP, monitor); - const screenBottomGap = Util.getScaledGap(Settings.SCREEN_BOTTOM_GAP, monitor); - const singleScreenGap = Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); - const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, monitor); - const r = this.copy(); - - // Prefer individual gaps - if (Util.useIndividualGaps(monitor)) { - [['x', 'width', screenLeftGap, screenRightGap], - ['y', 'height', screenTopGap, screenBottomGap]] - .forEach(([pos, dim, posGap, dimGap]) => { - if (this[pos] === workArea[pos]) { - r[pos] = this[pos] + posGap; - r[dim] -= posGap; - } else { - r[pos] = this[pos] + windowGap / 2; - r[dim] -= windowGap / 2; - } - - if (this[pos] + this[dim] === workArea[pos] + workArea[dim]) - r[dim] -= dimGap; - else - r[dim] -= windowGap / 2; - }); - // Use the single screen gap - } else { - [['x', 'width'], ['y', 'height']].forEach(([pos, dim]) => { - if (this[pos] === workArea[pos]) { - r[pos] = this[pos] + singleScreenGap; - r[dim] -= singleScreenGap; - } else { - r[pos] = this[pos] + windowGap / 2; - r[dim] -= windowGap / 2; - } - - if (this[pos] + this[dim] === workArea[pos] + workArea[dim]) - r[dim] -= singleScreenGap; - else - r[dim] -= windowGap / 2; - }); - } - - return r; - } - - /** - * Checks whether `this` borders another rectangle on this' east edge. - * - * @param {Rect} rect - * @returns {boolean} - */ - bordersOnE(rect) { - return this.vertOverlap && this.x2 === rect.x; - } - - /** - * Checks whether `this` borders another rectangle on this' south edge. - * - * @param {Rect} rect - * @returns {boolean} - */ - bordersOnS(rect) { - return this.horizOverlap && this.y2 === rect.y; - } - - /** - * @param {{x: number, y: number}} point - * @returns {boolean} - */ - containsPoint(point) { - return point.x >= this.x && point.x <= this.x2 && - point.y >= this.y && point.y <= this.y2; - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - containsRect(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.contains_rect(rect); - } - - /** - * @returns {Rect} - */ - copy() { - return new Rect(this._rect); - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - couldFitRect(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.could_fit_rect(rect); - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - equal(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.equal(rect); - } - - /** - * Gets the neighbor in the direction `dir` within the list of Rects - * `rects`. - * - * @param {Direction} dir the direction that is looked into. - * @param {Rect[]} rects an array of the available Rects. It may contain - * `this` itself. The rects shouldn't overlap each other. - * @param {boolean} [wrap=true] whether wrap is enabled, - * if there is no Rect in the direction of `dir`. - * @returns {Rect|null} the nearest Rect. - */ - getNeighbor(dir, rects, wrap = true) { - // Since we can only move into 1 direction at a time, we just need - // to check 1 axis / property of the rects per movement (...almost). - // An example probably makes this clearer. If we want to get the - // neighbor in the N direction, we just look at the y's of the rects. - // More specifically, we look for the y2's ('cmprProp') of the other - // rects which are bigger than the y1 ('startProp') of `this`. The - // nearest neighbor has y2 == this.y1. i. e. the neighbor and `this` - // share a border. There may be multiple windows with the same distance. - // In our example it might happen, if 2 windows are tiled side by side - // bordering `this`. In that case we choose the window, which is the - // nearest on the non-compared axis ('nonCmprProp'). The x property - // in the this example. - let startProp, cmprProp, nonCmprProp; - if (dir === Direction.N) - [startProp, cmprProp, nonCmprProp] = ['y', 'y2', 'x']; - else if (dir === Direction.S) - [startProp, cmprProp, nonCmprProp] = ['y2', 'y', 'x']; - else if (dir === Direction.W) - [startProp, cmprProp, nonCmprProp] = ['x', 'x2', 'y']; - else if (dir === Direction.E) - [startProp, cmprProp, nonCmprProp] = ['x2', 'x', 'y']; - - // Put rects into a Map with their relevenat pos'es as the keys and - // filter out `this`. - const posMap = rects.reduce((map, rect) => { - if (rect.equal(this)) - return map; - - const pos = rect[cmprProp]; - if (!map.has(pos)) - map.set(pos, []); - - map.get(pos).push(rect); - return map; - }, new Map()); - - // Sort the pos'es in an ascending / descending order. - const goForward = [Direction.S, Direction.E].includes(dir); - const sortedPoses = [...posMap.keys()].sort((a, b) => - goForward ? a - b : b - a); - - const neighborPos = goForward - ? sortedPoses.find(pos => pos >= this[startProp]) - : sortedPoses.find(pos => pos <= this[startProp]); - - if (!neighborPos && !wrap) - return null; - - // Since the sortedPoses array is in descending order when 'going - // backwards', we always wrap by getting the 0-th item, if there - // is no actual neighbor. - const neighbors = posMap.get(neighborPos ?? sortedPoses[0]); - return neighbors.reduce((currNearest, rect) => { - return Math.abs(currNearest[nonCmprProp] - this[nonCmprProp]) <= - Math.abs(rect[nonCmprProp] - this[nonCmprProp]) - ? currNearest - : rect; - }); - } - - /** - * Gets the rectangle at `index`, if `this` is split into equally - * sized rects. This function is meant to prevent rounding errors. - * Rounding errors may lead to rects not aligning properly and thus - * messing up other calculations etc... This solution may lead to the - * last rect's size being off by a few pixels compared to the other - * rects, if we split `this` multiple times. - * - * @param {number} index the position of the rectangle we want after - * splitting this rectangle. - * @param {number} unitSize the size of 1 partial unit of the rectangle. - * @param {Orientation} orientation determines the split orientation - * (horizontally or vertically). - * @returns {Rect} the rectangle at `index` after the split. - */ - getUnitAt(index, unitSize, orientation) { - unitSize = Math.floor(unitSize); - - const isVertical = orientation === Orientation.V; - const lastIndex = Math.round(this[isVertical ? 'width' : 'height'] / unitSize) - 1; - - const getLastRect = () => { - const margin = unitSize * index; - return new Rect( - isVertical ? this.x + margin : this.x, - isVertical ? this.y : this.y + margin, - isVertical ? this.width - margin : this.width, - isVertical ? this.height : this.height - margin - ); - }; - const getNonLastRect = (remainingRect, idx) => { - const firstUnitRect = new Rect( - remainingRect.x, - remainingRect.y, - isVertical ? unitSize : remainingRect.width, - isVertical ? remainingRect.height : unitSize - ); - - if (idx <= 0) { - return firstUnitRect; - } else { - const remaining = remainingRect.minus(firstUnitRect)[0]; - return getNonLastRect(remaining, idx - 1); - } - }; - - if (index === lastIndex) - return getLastRect(); - else - return getNonLastRect(this, index); - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - horizOverlap(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.horiz_overlap(rect); - } - - /** - * @param {Rect} rect - * @returns {[boolean, Rect]} - */ - intersect(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - const [ok, intersection] = this._rect.intersect(rect); - return [ok, new Rect(intersection)]; - } - - /** - * Get the Rects that remain from `this`, if `r` is cut off from it. - * - * @param {Rect|Rect[]} r either a single Rect or an array of Rects. - * @returns {Rect[]} an array of Rects. - */ - minus(r) { - return Array.isArray(r) ? this._minusRectArray(r) : this._minusRect(r); - } - - /** - * Gets the Rects, which remain from `this` after `rect` was cut off - * / subtracted from it. - * - * Original idea from: \ - * https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Rectangle_difference \ - * No license is given except the general CC-BY-AS (for text) mentioned - * in the footer. Since the algorithm seems fairly generic (just a few - * additions / substractions), I think I should be good regardless... - * I've modified the algorithm to make the left / right result rects bigger - * instead of the top / bottom rects since screens usually have horizontal - * orientations; so having the vertical rects take priority makes more sense. - * - * @param {Rect} rect the Rect to cut off from `this`. - * @returns {Rect[]} an array of Rects. It contains 0 - 4 rects. - */ - _minusRect(rect) { - rect = rect instanceof Mtk.Rectangle ? new Rect(rect) : rect; - if (rect.containsRect(this)) - return []; - - const [intersect] = this.intersect(rect); - if (!intersect) - return [this.copy()]; - - const resultRects = []; - - // Left rect - const leftRectWidth = rect.x - this.x; - if (leftRectWidth > 0 && this.height > 0) - resultRects.push(new Rect(this.x, this.y, leftRectWidth, this.height)); - - // Right rect - const rightRectWidth = this.x2 - rect.x2; - if (rightRectWidth > 0 && this.height > 0) - resultRects.push(new Rect(rect.x2, this.y, rightRectWidth, this.height)); - - const vertRectsX1 = rect.x > this.x ? rect.x : this.x; - const vertRectsX2 = rect.x2 < this.x2 ? rect.x2 : this.x2; - const vertRectsWidth = vertRectsX2 - vertRectsX1; - - // Top rect - const topRectHeight = rect.y - this.y; - if (topRectHeight > 0 && vertRectsWidth > 0) - resultRects.push(new Rect(vertRectsX1, this.y, vertRectsWidth, topRectHeight)); - - // Bottom rect - const bottomRectHeight = this.y2 - rect.y2; - if (bottomRectHeight > 0 && vertRectsWidth > 0) - resultRects.push(new Rect(vertRectsX1, rect.y2, vertRectsWidth, bottomRectHeight)); - - return resultRects; - } - - /** - * Gets the Rects that remain from `this`, if a list of rects is cut - * off from it. - * - * @param {Rect[]} rects the list of Rects to cut off from `this`. - * @returns {Rect[]} an array of the remaining Rects. - */ - _minusRectArray(rects) { - if (!rects.length) - return [this.copy()]; - - // First cut off all rects individually from `this`. The result is an - // array of leftover rects (which are arrays themselves) from `this`. - const individualLeftOvers = rects.map(r => this.minus(r)); - - // Get the final result by intersecting all leftover rects. - return individualLeftOvers.reduce((result, currLeftOvers) => { - const intersections = []; - - for (const leftOver of currLeftOvers) { - for (const currFreeRect of result) { - const [ok, inters] = currFreeRect.intersect(leftOver); - ok && intersections.push(new Rect(inters)); - } - } - - return intersections; - }); - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - overlap(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.overlap(rect); - } - - /** - * Makes `this` stick to `rect`, if they are close to each other. Use it - * as a last resort to prevent rounding errors, if you can't use minus() - * or getUnitAt(). - * - * @param {Rect} rect the rectangle to align `this` with. - * @param {number} margin only align, if `this` and the `rect` are at most - * this far away. - * @returns {Rect} a reference to this. - */ - tryAlignWith(rect, margin = 4) { - rect = rect instanceof Mtk.Rectangle ? new Rect(rect) : rect; - const equalApprox = (value1, value2) => Math.abs(value1 - value2) <= margin; - - if (equalApprox(rect.x, this.x)) - this.x = rect.x; - else if (equalApprox(rect.x2, this.x)) - this.x = rect.x2; - - if (equalApprox(rect.y, this.y)) - this.y = rect.y; - else if (equalApprox(rect.y2, this.y)) - this.y = rect.y2; - - if (equalApprox(rect.x, this.x2)) - this.width = rect.x - this.x; - else if (equalApprox(rect.x2, this.x2)) - this.width = rect.x2 - this.x; - - if (equalApprox(rect.y, this.y2)) - this.height = rect.y - this.y; - else if (equalApprox(rect.y2, this.y2)) - this.height = rect.y2 - this.y; - - return this; - } - - /** - * @param {Rect} rect - * @returns {Rect} - */ - union(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return new Rect(this._rect.union(rect)); - } - - /** - * @param {Rect} rect - * @returns {boolean} - */ - vertOverlap(rect) { - rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; - return this._rect.vert_overlap(rect); - } - - /** - * Getters - */ - - get meta() { - return this._rect.copy(); - } - - get area() { - return this._rect.area(); - } - - get x() { - return this._rect.x; - } - - get x2() { - return this._rect.x + this._rect.width; - } - - get y() { - return this._rect.y; - } - - get y2() { - return this._rect.y + this._rect.height; - } - - get center() { - return { - x: this.x + Math.floor(this.width / 2), - y: this.y + Math.floor(this.height / 2) - }; - } - - get width() { - return this._rect.width; - } - - get height() { - return this._rect.height; - } - - /** - * Setters - */ - - set x(value) { - this._rect.x = Math.floor(value); - } - - set x2(value) { - this._rect.width = Math.floor(value) - this.x; - } - - set y(value) { - this._rect.y = Math.floor(value); - } - - set y2(value) { - this._rect.height = Math.floor(value) - this.y; - } - - set width(value) { - this._rect.width = Math.floor(value); - } - - set height(value) { - this._rect.height = Math.floor(value); - } -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/layouts_example.json b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/layouts_example.json deleted file mode 100644 index 71e7c04..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/layouts_example.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "_name": "Master and Stack [V]", - "_items": [ - { - "rect": { - "x": 0, - "y": 0, - "width": 0.5, - "height": 1 - }, - "appId": null, - "loopType": null - }, - { - "rect": { - "x": 0.5, - "y": 0, - "width": 0.5, - "height": 1 - }, - "appId": null, - "loopType": "h" - } - ] - }, - { - "_name": "N-Columns", - "_items": [ - { - "rect": { - "x": 0, - "y": 0, - "width": 1, - "height": 1 - }, - "appId": null, - "loopType": "v" - } - ] - }, - { - "_name": "2 : 1 [V]", - "_items": [ - { - "rect": { - "x": 0, - "y": 0, - "width": 0.66, - "height": 1 - }, - "appId": null, - "loopType": null - }, - { - "rect": { - "x": 0.66, - "y": 0, - "width": 0.34, - "height": 1 - }, - "appId": null, - "loopType": null - } - ] - }, - { - "_name": "4 Quarters", - "_items": [ - { - "rect": { - "x": 0, - "y": 0, - "width": 0.5, - "height": 0.5 - }, - "appId": null, - "loopType": null - }, - { - "rect": { - "x": 0.5, - "y": 0, - "width": 0.5, - "height": 0.5 - }, - "appId": null, - "loopType": null - }, - { - "rect": { - "x": 0, - "y": 0.5, - "width": 0.5, - "height": 0.5 - }, - "appId": null, - "loopType": null - }, - { - "rect": { - "x": 0.5, - "y": 0.5, - "width": 0.5, - "height": 0.5 - }, - "appId": null, - "loopType": null - } - ] - } -] \ No newline at end of file diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRow.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRow.js deleted file mode 100644 index 437b97c..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRow.js +++ /dev/null @@ -1,221 +0,0 @@ -import { Gdk, Gtk, GObject } from '../dependencies/prefs/gi.js'; -import { _ } from '../dependencies/prefs.js'; - -import { Layout } from '../common.js'; -import { LayoutRowEntry } from './layoutRowEntry.js'; - -/** - * 1 LayoutRow represents 1 Layout in the preference window. It's just instanced - * by layoutsPrefs.js (see that file for more details and general information - * about layouts). 1 LayoutRow has a bunch of LayoutRowEntries, which each - * represent a LayoutItem. A LayoutItem is a simple JS Object and has a - * { rect, appId, loopType }. The rect is mandatory, the rest not. - */ - -export const LayoutRow = GObject.registerClass({ - GTypeName: 'TilingLayoutRow', - Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), - InternalChildren: [ - 'addRowEntryButton', - 'deleteButton', - 'drawingArea', - 'entryBox', - 'errorLabel', - 'expanderButton', - 'nameEntry', - 'rectCountLabel', - 'shortcut', - 'revealer' - ], - Signals: { 'changed': { param_types: [GObject.TYPE_BOOLEAN] } } -}, class TilingLayoutRow extends Gtk.ListBoxRow { - // Use a static variable to make sure the indices are unique since just using - // something like the child index isn't enough because the user may add *and* - // delete rows at random... so 1 child index may appear multiple times - static instanceCount = 0; - - /** - * @returns {number} the number of created LayoutRows since the last time - * the layouts were loaded into the preference window. - */ - static getInstanceCount() { - return TilingLayoutRow.instanceCount; - } - - static resetInstanceCount() { - TilingLayoutRow.instanceCount = 0; - } - - /** - * @param {{_name: string, _items: {rect: object, appId: ?string, loopType: ?string}[] - * }|null} layout a parsed JS object representing a layout from the - * layouts.json file. - */ - _init(layout, settings) { - super._init(); - - this._settings = settings; - this._layout = new Layout(layout); - this._idx = TilingLayoutRow.instanceCount++; - this._shortcutKey = `activate-layout${this._idx}`; - - // Initialize shortcut and its clear-button - this._shortcut.initialize(this._shortcutKey, this._settings); - - // Set name. Don't use a placeholder, if there is one because of a bug - // when reloading the layouts - const name = this._layout.getName(); - this._nameEntry.get_buffer().set_text(name, -1); - this._nameEntry.set_placeholder_text(name ? '' : 'Nameless Layout...'); - - // Load the entries with values from the layout - const items = this._layout.getItems(); - items.forEach((item, idx) => { - const rowEntry = new LayoutRowEntry(idx, item); - rowEntry.connect('changed', this._onRowEntryChanged.bind(this)); - this._entryBox.append(rowEntry); - }); - - // Show the nr of rects for a quicker overview. - this._rectCountLabel.set_label(items.length ? `(${items.length})` : ''); - - // Add one empty entry row - this._onAddRowEntryButtonClicked(); - - // Update the preview / show the errorLabel - this._updatePreview(); - } - - destroy() { - this.get_parent().remove(this); - } - - activate() { - this._nameEntry.grab_focus(); - } - - /** - * toggles whether the layout's rects are visible. - */ - toggleReveal() { - this._revealer.reveal_child = !this._revealer.reveal_child; - } - - /** - * @returns {number} the index of this layout. - */ - getIdx() { - return this._idx; - } - - /** - * @returns {{_name: string, _items: {rect: object, appId: ?string, loopType: ?string}[] - * }|null} the layout object represented by this row. - */ - getLayout() { - // First, filter out empty rows (i. e. rows without valid rects) - this._layout.setItems(this._layout.getItems()); - - // Then, remove problematic items, if the rects have problems. E. g., - // they may overlap each other, extend outside of the screen etc... - // This is irreversible but fine since this function is only called - // when the user presses the save button. Before that there will be - // error messages shown in the preview area. - let [ok, , idx] = this._layout.validate(); - while (this._layout.getItemCount() && !ok) { - this._layout.removeItem(idx); - [ok, , idx] = this._layout.validate(); - } - - return this._layout.getItemCount() ? this._layout : null; - } - - /** - * @returns {[boolean, string]} whether the preview was successful and a - * potential error message. - */ - _updatePreview() { - const [ok, errMsg] = this._layout.validate(); - if (!ok) { - // Print error in the preview area - this._errorLabel.set_label(errMsg); - this._drawingArea.set_draw_func(() => {}); - } else { - // Draw the actual preview for the rects - this._errorLabel.set_label(''); - this._drawingArea.set_draw_func((drawingArea, cr) => { - const color = new Gdk.RGBA(); - const width = drawingArea.get_allocated_width(); - const height = drawingArea.get_allocated_height(); - - cr.setLineWidth(1.0); - - this._layout.getItems().forEach(item => { - // Rects are in a slightly transparent white with a 1px outline - // and a 5px gap between the different rects - const rect = item.rect; - color.parse('rgba(255, 255, 255, .2)'); - Gdk.cairo_set_source_rgba(cr, color); - cr.moveTo(rect.x * width + 5, rect.y * height + 5); - cr.lineTo((rect.x + rect.width) * width - 5, rect.y * height + 5); - cr.lineTo((rect.x + rect.width) * width - 5, (rect.y + rect.height) * height - 5); - cr.lineTo(rect.x * width + 5, (rect.y + rect.height) * height - 5); - cr.lineTo(rect.x * width + 5, rect.y * height + 5); - cr.strokePreserve(); - - // Fill the rects in transparent black. - // If the rect is a 'loop', lower the transparency. - color.parse(`rgba(0, 0, 0, ${item.loopType ? .1 : .3})`); - Gdk.cairo_set_source_rgba(cr, color); - cr.fill(); - }); - - cr.$dispose(); - }); - } - - this._drawingArea.queue_draw(); - return [ok, errMsg]; - } - - _onNameEntryChanged() { - const name = this._nameEntry.get_buffer().get_text(); - this._nameEntry.set_tooltip_text(name); - this._layout.setName(name); - const [ok] = this._layout.validate(); - this.emit('changed', ok); - } - - _onDeleteButtonClicked() { - this._settings.set_strv(this._shortcutKey, []); - this.emit('changed', true); - this.destroy(); - } - - _onExpanderButtonClicked() { - this.toggleReveal(); - } - - _onClearShortcutButtonClicked() { - this._settings.set_strv(`activate-layout${this._idx}`, []); - } - - _onAddRowEntryButtonClicked() { - const rowEntry = new LayoutRowEntry(this._layout.getItemCount(), this._layout.addItem()); - rowEntry.connect('changed', this._onRowEntryChanged.bind(this)); - this._entryBox.append(rowEntry); - } - - _onRowEntryChanged(entry, ok) { - // ok only is about the change being ok for the *individual* entry - // i. e. whether their format is correct - if (!ok) { - this.emit('changed', ok); - return; - } - - // allOk is about whether the guiEntries are also valid as a whole - const [allOk] = this._updatePreview(); - this.emit('changed', allOk); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js deleted file mode 100644 index 073b684..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js +++ /dev/null @@ -1,124 +0,0 @@ -import { Gio, Gtk, GObject } from '../dependencies/prefs/gi.js'; -import { _ } from '../dependencies/prefs.js'; - -/** - * Multiple LayoutRowEntries make up a LayoutRow.js. See that file for more info. - */ - -export const LayoutRowEntry = GObject.registerClass({ - GTypeName: 'TilingLayoutRowEntry', - Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), - InternalChildren: [ - 'rectEntry', - 'rectLabel', - 'rectAppButton' - ], - Signals: { 'changed': { param_types: [GObject.TYPE_BOOLEAN] } } -}, class TilingLayoutRowEntry extends Gtk.Box { - _init(idx, item) { - super._init({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 8 - }); - - this._item = item; - - this._rectLabel.set_label(`Rect ${idx}`); - const loop = item.loopType ? `--${item.loopType}` : ''; - const rect = item.rect; - const text = Object.keys(rect).length !== 0 - ? `${rect.x}--${rect.y}--${rect.width}--${rect.height}${loop}` - : ''; - this._rectEntry.get_buffer().set_text(text, -1); - - // Show a placeholder on the first entry, if it's empty - if (!text) { - if (idx === 0) { - const placeholder = _("'User Guide' for help..."); - this._rectEntry.set_placeholder_text(placeholder); - } else { - this._rectEntry.set_placeholder_text('x--y--width--height[--h|v]'); - } - } - - const appInfo = item.appId && Gio.DesktopAppInfo.new(item.appId); - const iconName = appInfo?.get_icon().to_string() ?? 'list-add-symbolic'; - this._rectAppButton.set_icon_name(iconName); - } - - /** - * @param {Gtk.Button} appButton src of the event. - */ - _onAppButtonClicked() { - // Reset app button, if it already has an app attached - if (this._item.appId) { - this._rectAppButton.set_icon_name('list-add-symbolic'); - this._item.appId = null; - this.emit('changed', true); - - // Attach app to the button - } else { - const chooserDialog = new Gtk.AppChooserDialog({ modal: true }); - chooserDialog.get_widget().set({ show_all: true, show_other: true }); - chooserDialog.connect('response', (dlg, id) => { - if (id === Gtk.ResponseType.OK) { - const appInfo = chooserDialog.get_widget().get_app_info(); - const iconName = appInfo.get_icon().to_string(); - this._rectAppButton.set_icon_name(iconName); - this._item.appId = appInfo.get_id(); - this.emit('changed', true); - } - - chooserDialog.destroy(); - }); - - chooserDialog.show(); - } - } - - /** - * @param {Gtk.Entry} entry src of the event. - */ - _onRectEntryChanged(entry) { - const text = entry.get_buffer().get_text(); - const [ok] = this._validateFormat(text); - if (ok) { - const values = text.split('--'); - this._item.rect = { - x: parseFloat(values[0].trim()), - y: parseFloat(values[1].trim()), - width: parseFloat(values[2].trim()), - height: parseFloat(values[3].trim()) - }; - this._item.loopType = values[4] || null; - } else { - this._item.rect = {}; - this._item.loopType = null; - } - - this.emit('changed', ok); - } - - /** - * Validates whether `text` follows the format \ - * 'Float--Float--Float--Float[--String]' - * - * @param {string} text - * @returns {[boolean, string]} whether the `text` is valid and a - * potential error message. - */ - _validateFormat(text) { - const values = text.split('--'); - // 4 -> x, y, width, height; 5 -> additionally, a loopType - if (values.length < 4 || values.length > 5) - return [false, 'Wrong format: invalid count.']; - - const notJustNrs = ['x', 'y', 'width', 'height'].some((p, idx) => { - return Number.isNaN(parseFloat(values[idx].trim())); - }); - - return notJustNrs - ? [false, 'Wrong format: only numbers are allowed.'] - : [true, '']; - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutsPrefs.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutsPrefs.js deleted file mode 100644 index 8e93ae7..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/layoutsPrefs.js +++ /dev/null @@ -1,222 +0,0 @@ -import { Gio, GLib } from '../dependencies/prefs/gi.js'; - -import { LayoutRow } from './layoutRow.js'; - -/** - * This class takes care of everything related to layouts (at least on the - * preference side). It's only being instanced by prefs.js. After that, it - * loads / saves layouts from / to the disk and loads the gui for managing - * layouts. The gui is created by instancing a bunch of Gtk.ListBoxRows from - * layoutGui.js for each layout and putting them into a Gtk.ListBox from the - * prefs.ui file. - * - * A popup layout has a name (String) and an array of LayoutItems (JS Objects). - * A LayoutItem has a rect (JS Objects), an optional (String) appId and optional - * loopType (String). Only the rect is a mandatory. The name lets the user - * search for a layout with the 'Search popup layout' keybinding. The rectangle's - * properties range from 0 to 1 (-> relative scale to the monitor). After a layout - * is activated by the user, the 'Tiling Popup' will appear at every LayoutItem's - * rect and ask the user which of the open windows they want to tile to that rect. - * If a loopType is set, the Tiling Popup will keep spawning at that spot and - * all tiled windows will evenly share that rect until the user cancels the tiling - * popup. Only then will we jump to the next LayoutItem. Possible loopTypes: - * horizontal ('h') or vertical (any other non-empty string). This allows the - * user to create 'Master and Stack' type of layouts. If an appId is defined, - * instead of the Tiling Popup appearing, a new instance of the app will be - * opened and tiled to that rect (or at least I tried to do that). - * - * By default, the settings for layouts are hidden behind the 'Advanced / - * Experimental' switch because I used a lot of hacks / assumptions... and - * I am not even using the layouts myself. However, I don't want to remove - * an existing feature... thus it's hidden - */ - -export default class { - constructor(settings, builder, path) { - // Keep a reference to the settings for the shortcuts - this._settings = settings; - - // The Gtk.ListBox, which LayoutRows are added to - this._layoutsListBox = builder.get_object('layouts_listbox'); - - // Unique button to save changes made to all layouts to the disk. For - // simplicity, reload from file after saving to get rid of invalid input. - this._saveLayoutsButton = builder.get_object('save_layouts_button'); - this._saveLayoutsButton.connect('clicked', () => { - this._saveLayouts(); - this._loadLayouts(); - }); - - // Unique button to load layouts from the disk - // (discarding all tmp changes) without any user prompt - this._reloadLayoutsButton = builder.get_object('reload_layouts_button'); - this._reloadLayoutsButton.connect('clicked', () => { - this._loadLayouts(); - }); - - // Unique button to add a new *tmp* LayoutRow - this._addLayoutButton = builder.get_object('add_layout_button'); - this._addLayoutButton.connect('clicked', () => { - const row = this._createLayoutRow(LayoutRow.getInstanceCount()); - row.toggleReveal(); - }); - - // Bind the general layouts keyboard shortcuts. - ['search-popup-layout'].forEach(key => { - const shortcut = builder.get_object(key.replaceAll('-', '_')); - shortcut.initialize(key, this._settings); - }); - - // Finally, load the existing settings. - this._loadLayouts(path); - } - - _loadLayouts(path) { - this._applySaveButtonStyle(''); - - this._forEachLayoutRow(row => row.destroy()); - LayoutRow.resetInstanceCount(); - - // Try to load layouts file. - const saveFile = this._makeFile(); - const [success, contents] = saveFile.load_contents(null); - if (!success) - return; - - let layouts = []; - - // Custom layouts are already defined in the file. - if (contents.length) { - layouts = JSON.parse(new TextDecoder().decode(contents)); - // Ensure at least 1 empty row otherwise the listbox won't have - // a height but a weird looking shadow only. - layouts.length - ? layouts.forEach((layout, idx) => this._createLayoutRow(idx, layout)) - : this._createLayoutRow(0); - - // Otherwise import the examples... but only do it once! - // Use a setting as a flag. - } else { - const importExamples = 'import-layout-examples'; - if (!this._settings.get_boolean(importExamples)) - return; - - this._settings.set_boolean(importExamples, false); - const exampleFile = this._makeFile(`${path}/src`, 'layouts_example.json'); - const [succ, c] = exampleFile.load_contents(null); - if (!succ) - return; - - layouts = c.length ? JSON.parse(new TextDecoder().decode(c)) : []; - layouts.forEach((layout, idx) => this._createLayoutRow(idx, layout)); - this._saveLayouts(); - } - } - - _saveLayouts() { - this._applySaveButtonStyle(''); - - const layouts = []; - this._forEachLayoutRow(layoutRow => { - const lay = layoutRow.getLayout(); - if (lay) { - layouts.push(lay); - - // Check, if all layoutRows were valid so far. Use getIdx() - // instead of forEach's idx because a layoutRow may have been - // deleted by the user. - if (layoutRow.getIdx() === layouts.length - 1) - return; - - // Invalid or empty layouts are ignored. For example, the user - // defined a valid layout with a keybinding on row idx 3 but left - // the row at idx 2 empty. When saving, the layout at idx 2 gets - // removed and layout at idx 3 takes its place (i. e. becomes - // idx 2). We need to update the keybindings to reflect that. - const keys = this._settings.get_strv(`activate-layout${layoutRow.getIdx()}`); - this._settings.set_strv(`activate-layout${layouts.length - 1}`, keys); - this._settings.set_strv(`activate-layout${layoutRow.getIdx()}`, []); - } else { - // Remove keyboard shortcuts, if they aren't assigned to a - // valid layout, because they won't be visible to the user - // since invalid layouts get removed - this._settings.set_strv(`activate-layout${layoutRow.getIdx()}`, []); - } - }); - - const saveFile = this._makeFile(); - saveFile.replace_contents( - JSON.stringify(layouts), - null, - false, - Gio.FileCreateFlags.REPLACE_DESTINATION, - null - ); - } - - /** - * @param {string} [parentPath=''] path to the parent directory. - * @param {string} [fileName=''] name of the layouts file. - * @returns {object} the Gio.File. - */ - _makeFile(parentPath = '', fileName = '') { - // Create directory structure, if it doesn't exist. - const userConfigDir = GLib.get_user_config_dir(); - const dirLocation = parentPath || - GLib.build_filenamev([userConfigDir, '/tiling-assistant']); - const parentDir = Gio.File.new_for_path(dirLocation); - try { parentDir.make_directory_with_parents(null); } catch (e) {} - - // Create file, if it doesn't exist. - const fName = fileName || 'layouts.json'; - const filePath = GLib.build_filenamev([dirLocation, '/', fName]); - const file = Gio.File.new_for_path(filePath); - try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} - - return file; - } - - /** - * @param {string} [actionName=''] possible styles: 'suggested-action' - * or 'destructive-action' - */ - _applySaveButtonStyle(actionName = '') { - // The suggested-action is used to indicate that the user made - // changes; the destructive-action, if saving will drop changes - // (e. g. when changes were invalid) - const actions = ['suggested-action', 'destructive-action']; - const context = this._saveLayoutsButton.get_style_context(); - actions.forEach(a => a === actionName - ? context.add_class(a) - : context.remove_class(a)); - } - - /** - * @param {number} index the index of the new layouts row. - * @param {Layout} layout the parsed JS Object from the layouts file. - */ - _createLayoutRow(index, layout = null) { - // Layouts are limited to 20 since there are only - // that many keybindings in the schemas.xml file - if (index >= 20) - return; - - const layoutRow = new LayoutRow(layout, this._settings); - layoutRow.connect('changed', (row, ok) => { - // Un / Highlight the save button, if the user made in / valid changes. - this._applySaveButtonStyle(ok ? 'suggested-action' : 'destructive-action'); - }); - this._layoutsListBox.append(layoutRow); - return layoutRow; - } - - _forEachLayoutRow(callback) { - for (let i = 0, child = this._layoutsListBox.get_first_child(); !!child; i++) { - // Get a ref to the next widget in case the curr widget - // gets destroyed during the function call. - const nxtSibling = child.get_next_sibling(); - callback.call(this, child, i); - child = nxtSibling; - } - } -} diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js deleted file mode 100644 index 29e8d32..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js +++ /dev/null @@ -1,208 +0,0 @@ -import { Adw, Gdk, GObject, Gtk } from '../dependencies/prefs/gi.js'; - -/** - * A Widget to implement the shortcuts in the preference window. - * It's an AdwActionRow, which contains a label showing the keybinding(s) - * and a shortcut-clear-button. - * - * Some parts are from https://extensions.gnome.org/extension/2236/night-theme-switcher/. - * _isBindingValid & _isKeyvalForbidden are straight up copied from its util.js - * https://gitlab.com/rmnvgr/nightthemeswitcher-gnome-shell-extension/-/blob/main/src/utils.js - */ - -export const ShortcutListener = GObject.registerClass({ - GTypeName: 'ShortcutListener', - Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), - InternalChildren: ['keybindingLabel', 'clearButton', 'eventKeyController'], - Properties: { - keybinding: GObject.ParamSpec.string( - 'keybinding', - 'Keybinding', - 'Key sequence', - GObject.ParamFlags.READWRITE, - null - ) - } -}, class ShortcutListener extends Adw.ActionRow { - /** - * Only allow 1 active ShortcutListener at a time - */ - static isListening = false; - static isAppendingShortcut = false; - static listener = null; - static listeningText = 'Press a shortcut...'; - static appendingText = 'Append a new shortcut...'; - - /** - * Starts listening for a keyboard shortcut. - * - * @param {ShortcutListener} shortcutListener the new active ShortcutListener - */ - static listen(shortcutListener) { - if (shortcutListener === ShortcutListener.listener) - return; - - ShortcutListener.stopListening(); - - shortcutListener.isActive = true; - shortcutListener.setKeybindingLabel(ShortcutListener.listeningText); - ShortcutListener.listener = shortcutListener; - ShortcutListener.isListening = true; - } - - /** - * Stops listening for a keyboard shortcut. - */ - static stopListening() { - if (!ShortcutListener.isListening) - return; - - ShortcutListener.isListening = false; - ShortcutListener.isAppendingShortcut = false; - ShortcutListener.listener.isActive = false; - ShortcutListener.listener.setKeybindingLabel(ShortcutListener.listener.getKeybindingLabel()); - ShortcutListener.listener = null; - } - - initialize(key, setting) { - this._key = key; - this._setting = setting; - this.isActive = false; - - this.connect('realize', () => this.get_root().add_controller(this._eventKeyController)); - - this.keybinding = this._setting.get_strv(key) ?? []; - } - - /* - * Sets the label of the keybinding. - */ - setKeybindingLabel(label) { - this._keybindingLabel.set_label(label); - } - - /** - * Gets the keybinding in a more pleasant to read format. - * For example: [e,a] will become - * 'Ctrl+Super+E / Super+A' or 'Disabled' - * - * @returns {string} - */ - getKeybindingLabel() { - const kbLabel = this.keybinding.reduce((label, kb) => { - const [, keyval, mask] = Gtk.accelerator_parse(kb); - const l = Gtk.accelerator_get_label(keyval, mask); - if (!label) - return l; - - return l ? `${label} / ${l}` : label; - }, ''); - - return kbLabel || 'Disabled'; - } - - _onActivated() { - this.isActive ? ShortcutListener.stopListening() : ShortcutListener.listen(this); - } - - _onKeybindingChanged() { - this._setting.set_strv(this._key, this.keybinding); - this._clearButton.set_sensitive(this.keybinding.length); - this.setKeybindingLabel(this.getKeybindingLabel()); - } - - _onClearButtonClicked() { - this.keybinding = []; - ShortcutListener.stopListening(); - } - - _onKeyPressed(eventControllerKey, keyval, keycode, state) { - if (this !== ShortcutListener.listener) - return Gdk.EVENT_PROPAGATE; - - let mask = state & Gtk.accelerator_get_default_mod_mask(); - mask &= ~Gdk.ModifierType.LOCK_MASK; - - if (mask === 0) { - switch (keyval) { - case Gdk.KEY_BackSpace: - this.keybinding = []; - // falls through - case Gdk.KEY_Escape: - ShortcutListener.stopListening(); - return Gdk.EVENT_STOP; - case Gdk.KEY_KP_Enter: - case Gdk.KEY_Return: - case Gdk.KEY_space: - ShortcutListener.isAppendingShortcut = !ShortcutListener.isAppendingShortcut; - this.setKeybindingLabel(ShortcutListener.isAppendingShortcut - ? ShortcutListener.appendingText - : ShortcutListener.listeningText - ); - return Gdk.EVENT_STOP; - } - } - - if (!this._isBindingValid({ mask, keycode, keyval }) || - !Gtk.accelerator_valid(keyval, mask)) - return Gdk.EVENT_STOP; - - const sc = Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask); - this.keybinding = ShortcutListener.isAppendingShortcut ? [...this.keybinding, sc] : [sc]; - - ShortcutListener.stopListening(); - return Gdk.EVENT_STOP; - } - - /** - * Checks, if the given key combo is a valid binding. - * - * @param {{mask: number, keycode: number, keyval:number}} combo An object - * representing the key combo. - * @returns {boolean} `true` if the key combo is a valid binding. - */ - _isBindingValid({ mask, keycode, keyval }) { - if ((mask === 0 || mask === Gdk.SHIFT_MASK) && keycode !== 0) { - if ( - (keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || - (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || - (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || - (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) || - (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || - (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || - (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) || - (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) || - (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || - (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || - (keyval === Gdk.KEY_space && mask === 0) || - this._isKeyvalForbidden(keyval) - ) - return false; - } - return true; - } - - /** - * Checks, if the given keyval is forbidden. - * - * @param {number} keyval The keyval number. - * @returns {boolean} `true` if the keyval is forbidden. - */ - _isKeyvalForbidden(keyval) { - const forbiddenKeyvals = [ - Gdk.KEY_Home, - Gdk.KEY_Left, - Gdk.KEY_Up, - Gdk.KEY_Right, - Gdk.KEY_Down, - Gdk.KEY_Page_Up, - Gdk.KEY_Page_Down, - Gdk.KEY_End, - Gdk.KEY_Tab, - Gdk.KEY_KP_Enter, - Gdk.KEY_Return, - Gdk.KEY_Mode_switch - ]; - return forbiddenKeyvals.includes(keyval); - } -}); diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRow.ui b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRow.ui deleted file mode 100644 index b702950..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRow.ui +++ /dev/null @@ -1,135 +0,0 @@ - - - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRowEntry.ui b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRowEntry.ui deleted file mode 100644 index aba78f9..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/layoutRowEntry.ui +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/prefs.ui b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/prefs.ui deleted file mode 100644 index a03b4d1..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/prefs.ui +++ /dev/null @@ -1,1139 +0,0 @@ - - - - - - - -
    - - Report a Bug - prefs.open-bug-report - - - User Guide - prefs.open-user-guide - - - License - prefs.open-license - - - Changelog - prefs.open-changelog - - - Advanced... - prefs.open-hidden-settings - -
    -
    - - - info-menu - dialog-information-symbolic - - - - - - - General - view-app-grid-symbolic - - - - - - Tiling Popup - - - Open after tiling a window - enable_tiling_popup - - - center - - - - - - - Include apps from all workspaces - tiling_popup_all_workspace - False - - - - center - - - - - - - - - - - - Tile Groups - - - Disable Tile Groups - Tiled windows will no longer adapt their size to other tiled windows nor be raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' and the Tiling Popup will also no longer work. - disable_tile_groups - - - - center - - - - - - - Raise together - A tile group is created when a window gets tiled. If a tiled window is raised, raise the other windows of its tile group as well - enable_raise_tile_group - - - center - - - - - - - App Switcher and Tiling Popup - This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You may need to re-enable this or the other extension after toggling this setting - tilegroups_in_app_switcher - - - - center - - - - - - - - - - - - Gaps - - - Windows - window_gap - - - center - - - 500 - 2 - 8 - - - - - - - - - Screen Edges - single_screen_gap - - - - center - - - 500 - 2 - 8 - - - - - - - - - Screen Edge Top - screen_top_gap - - - - center - - - 500 - 2 - 8 - - - - - - - - - Screen Edge Left - screen_left_gap - - - - center - - - 500 - 2 - 8 - - - - - - - - - Screen Edge Right - screen_right_gap - - - - center - - - 500 - 2 - 8 - - - - - - - - - Screen Edge Bottom - screen_bottom_gap - - - - center - - - 500 - 2 - 8 - - - - - - - - - Maximized Windows - maximize_with_gap - - - center - - - - - - - - - - - - Dynamic Keybinding Behavior - The keybindings to maximize and tile to the top/bottom/left/right may change their behavior based on the window's tiling state - - - Disabled - Don't change the keybindings' behavior - dynamic_keybinding_disabled_button - - - - - - - - Window Focus - Switch focus to the tiled window in the direction of the pressed shortcut - dynamic_keybinding_window_focus_button - - - dynamic_keybinding_disabled_button - - - - - - - Tiling State - Adapt the tiling state to the pressed shortcut. For instance, a window tiled to the right half will tile to the bottom-right quarter, if 'tile to bottom' is activated - dynamic_keybinding_tiling_state_button - - - dynamic_keybinding_disabled_button - - - - - - - Tiling State (Windows) - Like 'Tiling State' but if the window isn't tiled or is already tiled to the bottom and the 'tile to bottom' shortcut is activated, minimize the window - dynamic_keybinding_tiling_state_windows_button - - - dynamic_keybinding_disabled_button - - - - - - - Favorite Layout - Move the window along your favorite Layout - dynamic_keybinding_favorite_layout_button - - - - dynamic_keybinding_disabled_button - - - - - - - - - - - - Active Window Hint - - - Disabled - Don't indicate the focused window - active_window_hint_disabled_button - - - - - - - - Minimal - Temporarily indicate the focused window when switching to a workspace with multiple non-overlapping windows - active_window_hint_minimal_button - - - active_window_hint_disabled_button - - - - - - - Always - Always indicate the focused window unless it's maximized or in fullscreen. There are issues on Wayland with GTK4 popups - active_window_hint_always_button - - - active_window_hint_disabled_button - - - - - - - - - - - - Hint Color - The color of the frame indicating the focused window - active_window_hint_color_button - - - center - - - - - - - Border Size - The border size of the frame indicating the focused window for the always active hint - active_window_hint_border_size - - - center - - - 50 - 1 - 8 - - - - - - - - - Inner Border Size - The border for the always active hint reaching inside the window frame. This is meant to cover rounded corners. However, GTK4 popups on Wayland will put the window behind the hint for whatever reason... - active_window_hint_inner_border_size - - - center - - - 50 - 1 - 8 - - - - - - - - - - - - - - Animations - - - - Tiling - enable_tile_animations - - - center - - - - - - - Untiling - enable_untile_animations - - - center - - - - - - - - - - - - Default Window Movement Mode - - - - Edge Tiling - Moving the window to the screen edges or corners will open the default tile preview - edge_tiling_checkbutton - - - - - - - - Adaptive Tiling - Releasing the grab on a window while hovering over a tile will push the overlapped window(s) aside - adaptive_tiling_checkbutton - - - edge_tiling_checkbutton - - - - - - - Favorite Layout - The tile preview will stick to your favorite layout from the 'Layouts' page - favorite_layout_checkbutton - - - edge_tiling_checkbutton - - - - - - - Ignore Tiling Assistant - Use Edge Tiling without Tiling Assistant's features - ignore_ta_checkbutton - - - edge_tiling_checkbutton - - - - - - - - - - - - Other - - - Monitor Switch Grace Period - When a window is dragged to a new monitor the tile preview will stick to the old monitor for a very short time. This way you can tile windows by 'throwing' it towards any screen edge even if a monitor is bordering that edge. - monitor_switch_grace_period - - - center - - - - - - - Low Performance Movement Mode - Use this if there is a lag when moving windows around. This will however decrease the precision of the tile preview updates. - low_performance_move_mode - - - - center - - - - - - - Adapt 'Edge Tiling' to your Favorite Layout - adapt_edge_tiling_to_favorite_layout - - - - center - - - - - - - 'Adaptive Tiling' Move Mode Activator - - - - - Disabled - Ctrl - Alt - RMB - Super - - - - - - - - 'Favorite Layout' Move Mode Activator - - - - - Disabled - Ctrl - Alt - RMB - Super - - - - - - - - 'Ignore Tiling Assistant' Mode Activator - - - - - Disabled - Ctrl - Alt - RMB - Super - - - - - - - - Vertical Edge Preview Trigger Area - vertical_preview_area - - - - center - - - 5 - 500 - 5 - 10 - - - - - - - - - Horizontal Edge Preview Trigger Area - horizontal_preview_area - - - - center - - - 10 - 500 - 5 - 10 - - - - - - - - - Inverse Top Screen Edge Action Timer - toggle_maximize_tophalf_timer - - - - center - - - 300 - 1500 - 50 - 10 - - - - - - - - - Inverse Top Screen Edge Action for Landscape Displays - enable_hold_maximize_inverse_landscape - - - - center - - - - - - - Inverse Top Screen Edge Action for Portrait Displays - enable_hold_maximize_inverse_portrait - - - - center - - - - - - - Restore Window Size on - Tiled windows may not properly restore their size on Wayland. If that's the case, use 'Restore Window Size on Grab End' - - - - - Grab Start - Grab End - - - - - - - - - - - - - - Keybindings - preferences-desktop-keyboard-symbolic - - - - - - General - - - Toggle 'Tiling Popup' - - - - - Tile Editing Mode - A keyboard-driven mode to manage your tiled windows - - - - - Auto-Tile - Un/tile the current window based on the visible tiles - - - - - Toggle 'Always on Top' - - - - - - Toggle Maximization - - - - - Toggle Vertical Maximization - - - - - - Toggle Horizontal Maximization - - - - - - Restore Window Size - - - - - Move Window to Center - - - - - - - - - - Edge Tiling - - - Tile to top - - - - - Tile to bottom - - - - - Tile to left - - - - - Tile to right - - - - - - - - - - Corner Tiling - - - Tile to top-left - - - - - Tile to top-right - - - - - Tile to bottom-left - - - - - Tile to bottom-right - - - - - - - - - - Edge Tiling without Tiling Assistant - - - - Tile to top - - - - - Tile to bottom - - - - - Tile to left - - - - - Tile to right - - - - - - - - - - Corner Tiling without Tiling Assistant - - - - Tile to top-left - - - - - Tile to top-right - - - - - Tile to bottom-left - - - - - Tile to bottom-right - - - - - - - - - - Debugging - - - - Show Tiled Rects - - - - - Show Free Screen Rects - - - - - - - - - - - Layouts - video-joined-displays-symbolic - - - - - - - General - - - Panel Indicator - show_layout_panel_indicator - - - center - - - - - - - Search for a Layout - Open a popup listing all the available layouts - - - - - - - - - - Layouts - - - none - - - - - - - - - - - - - center - end - - - 100 - list-add-symbolic - Add a new Layout. - - - - - 100 - media-floppy-symbolic - Save the layouts to the disk. Invalid changes will be lost! - - - - - 100 - edit-undo-symbolic - Reload the layouts from the disk - discarding all non-saved changes. - - - - - - - - - - - - - - - - - - go-previous-symbolic - start - start - 6 - 6 - - - - - - center - 1 - - - 12 - - - vertical - - - 96 - dialog-warning-symbolic - - - - - - - - - - - - - - Advanced / Experimental Settings - Show more settings in the main preference window - enable_advanced_experimental_features - - - center - - - - - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui deleted file mode 100644 index 6140a19..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - diff --git a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/stylesheet.css b/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/stylesheet.css deleted file mode 100644 index 2787811..0000000 --- a/.local/share/gnome-shell/extensions/tiling-assistant@leleat-on-github/stylesheet.css +++ /dev/null @@ -1,8 +0,0 @@ -.tiling-layout-search-highlight { - background-color: rgba(255, 255, 255, 0.1); - border-radius: 20px; -} - -.layout-shortcut .boxed-list { - box-shadow: none; -} diff --git a/.local/share/gnome-shell/update-check-45 b/.local/share/gnome-shell/update-check-45 deleted file mode 100644 index e69de29..0000000
  • -   - - -   - - - -